home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / CompilerParser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  115.6 KB  |  3,778 lines  |  [TEXT/KAHL]

  1. /* CompilerParser.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "CompilerParser.h"
  31. #include "CompilerScanner.h"
  32. #include "SymbolTableEntry.h"
  33. #include "ASTExpression.h"
  34. #include "SymbolTable.h"
  35. #include "TrashTracker.h"
  36. #include "SymbolList.h"
  37. #include "PcodeObject.h"
  38. #include "Memory.h"
  39. #include "ASTAssignment.h"
  40. #include "ASTBinaryOperator.h"
  41. #include "ASTErrorForm.h"
  42. #include "ASTLoop.h"
  43. #include "ASTArrayDeclaration.h"
  44. #include "ASTVariableDeclaration.h"
  45. #include "ASTConditional.h"
  46. #include "ASTUnaryOperator.h"
  47. #include "ASTOperand.h"
  48. #include "ASTFuncCall.h"
  49. #include "ASTExpressionList.h"
  50. #include "ASTWaveGetter.h"
  51. #include "ASTPrintString.h"
  52. #include "ASTPrintExpr.h"
  53. #include "FloatingPoint.h"
  54.  
  55.  
  56. /* protoplops */
  57. static CompileErrors    ParseFunction(SymbolRec** FunctionSymbolTableEntryOut,
  58.                                                 ASTExpressionRec** FunctionBodyOut,
  59.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  60.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  61.  
  62. static CompileErrors    ParsePrototype(SymbolRec** PrototypeSymbolTableEntryOut,
  63.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  64.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  65.  
  66. static CompileErrors    ParseFormalParamStart(SymbolListRec** FormalArgListOut,
  67.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  68.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  69.  
  70. static CompileErrors    ParseType(DataTypes* TypeOut, ScannerRec* Scanner,
  71.                                                 long* LineNumberOut);
  72.  
  73. static CompileErrors    ParseFormalParamList(SymbolListRec** FormalArgListOut,
  74.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  75.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  76.  
  77. static CompileErrors    ParseVarTail(ASTExpressionRec** ExpressionOut,
  78.                                                 TokenRec* VariableName, long VariableDeclLine,
  79.                                                 DataTypes VariableType, ScannerRec* Scanner,
  80.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  81.                                                 long* LineNumberOut);
  82.  
  83. static CompileErrors    ParseIfRest(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  84.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  85.                                                 long* LineNumberOut);
  86.  
  87. static CompileErrors    ParseWhileLoop(ASTExpressionRec** ExpressionOut,
  88.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  89.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  90.  
  91. static CompileErrors    ParseLoopWhileUntil(ASTExpressionRec** ExpressionOut,
  92.                                                 ASTExpressionRec* LoopBodyExpression, ScannerRec* Scanner,
  93.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  94.                                                 long* LineNumberOut, long LineNumberOfLoop);
  95.  
  96. static CompileErrors    ParseUntilLoop(ASTExpressionRec** ExpressionOut,
  97.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  98.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  99.  
  100. static CompileErrors    ParseExpr2(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  101.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  102.                                                 long* LineNumberOut);
  103.  
  104. static CompileErrors    ParseFormalArg(SymbolRec** FormalArgOut, ScannerRec* Scanner,
  105.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  106.                                                 long* LineNumberOut);
  107.  
  108. static CompileErrors    ParseFormalArgTail(SymbolListRec** ArgListTailOut,
  109.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  110.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  111.  
  112. static CompileErrors    ParseIfTail(ASTExpressionRec** ExpressionOut,
  113.                                                 ASTExpressionRec* Predicate, ASTExpressionRec* Consequent,
  114.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  115.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  116.  
  117. static CompileErrors    ParseExpr3(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  118.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  119.                                                 long* LineNumberOut);
  120.  
  121. static CompileErrors    ParseExpr2Prime(ASTExpressionRec** ExpressionOut,
  122.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  123.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  124.                                                 long* LineNumberOut);
  125.  
  126. static CompileErrors    ParseExpr4(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  127.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  128.                                                 long* LineNumberOut);
  129.  
  130. static CompileErrors    ParseExpr3Prime(ASTExpressionRec** ExpressionOut,
  131.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  132.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  133.                                                 long* LineNumberOut);
  134.  
  135. static CompileErrors    ParseConjOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  136.                                                 long* LineNumberOut);
  137.  
  138. static CompileErrors    ParseExpr5(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  139.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  140.                                                 long* LineNumberOut);
  141.  
  142. static CompileErrors    ParseExpr4Prime(ASTExpressionRec** ExpressionOut,
  143.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  144.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  145.                                                 long* LineNumberOut);
  146.  
  147. static CompileErrors    ParseRelOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  148.                                                 long* LineNumberOut);
  149.  
  150. static CompileErrors    ParseExpr6(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  151.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  152.                                                 long* LineNumberOut);
  153.  
  154. static CompileErrors    ParseExpr5Prime(ASTExpressionRec** ExpressionOut,
  155.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  156.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  157.                                                 long* LineNumberOut);
  158.  
  159. static CompileErrors    ParseAddOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  160.                                                 long* LineNumberOut);
  161.  
  162. static CompileErrors    ParseExpr7(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  163.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  164.                                                 long* LineNumberOut);
  165.  
  166. static CompileErrors    ParseMultOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  167.                                                 long* LineNumberOut);
  168.  
  169. static CompileErrors    ParseExpr8(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  170.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  171.                                                 long* LineNumberOut);
  172.  
  173. static CompileErrors    ParseExpr7Prime(ASTExpressionRec** ExpressionOut,
  174.                                                 ASTExpressionRec* TheExpr8Thing, ScannerRec* Scanner,
  175.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  176.                                                 long* LineNumberOut);
  177.  
  178. static CompileErrors    ParseFuncCall(ASTExpressionRec** ExpressionOut,
  179.                                                 ASTExpressionRec* FunctionGenerator, ScannerRec* Scanner,
  180.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  181.                                                 long* LineNumberOut);
  182.  
  183. static CompileErrors    ParseArraySubscript(ASTExpressionRec** ExpressionOut,
  184.                                                 ASTExpressionRec* ArrayGenerator, ScannerRec* Scanner,
  185.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  186.                                                 long* LineNumberOut);
  187.  
  188. static CompileErrors    ParseExponentiation(ASTExpressionRec** ExpressionOut,
  189.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  190.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  191.  
  192. static CompileErrors    ParseActualStart(ASTExprListRec** ParamListOut,
  193.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  194.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  195.  
  196. static CompileErrors    ParseActualList(ASTExprListRec** ParamListOut,
  197.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  198.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  199.  
  200. static CompileErrors    ParseActualTail(ASTExprListRec** ParamListOut,
  201.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  202.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  203.  
  204. static CompileErrors    ParseExprListTail(ASTExprListRec** ListOut,
  205.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  206.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  207.  
  208. static CompileErrors    ParseExprListElem(ASTExpressionRec** ExpressionOut,
  209.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  210.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  211.  
  212.  
  213.  
  214.  
  215. /* parse a top-level form, which is either a prototype or a function.  prototypes */
  216. /* are entered into the symbol table and return NIL in *FunctionBodyOut but returns */
  217. /* eCompileNoError. */
  218. /*   1:   <form>             ::= <function> ; */
  219. /*   2:                      ::= <prototype> ; */
  220. /* FIRST SET: */
  221. /* <form>             : {func, proto, <function>, <prototype>} */
  222. /* FOLLOW SET: */
  223. /* <form>             : {$$$} */
  224. CompileErrors                    ParseForm(struct SymbolRec** FunctionSymbolTableEntryOut,
  225.                                                 struct ASTExpressionRec** FunctionBodyOut,
  226.                                                 struct ScannerRec* Scanner, struct SymbolTableRec* SymbolTable,
  227.                                                 struct TrashTrackRec* TrashTracker, long* LineNumberOut)
  228.     {
  229.         TokenRec*                        Token;
  230.         CompileErrors                Error;
  231.  
  232.         Token = GetNextToken(Scanner);
  233.         if (Token == NIL)
  234.             {
  235.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  236.                 return eCompileOutOfMemory;
  237.             }
  238.  
  239.         /* do lookahead on "func" */
  240.         if ((GetTokenType(Token) == eTokenKeyword)
  241.             && (GetTokenKeywordTag(Token) == eKeywordFunc))
  242.             {
  243.                 /* push token back */
  244.                 UngetToken(Scanner,Token);
  245.  
  246.                 /* parse function definition */
  247.                 Error = ParseFunction(FunctionSymbolTableEntryOut,FunctionBodyOut,
  248.                     Scanner,SymbolTable,TrashTracker,LineNumberOut);
  249.                 if (Error != eCompileNoError)
  250.                     {
  251.                         return Error;
  252.                     }
  253.             }
  254.  
  255.         /* do lookahead on "proto" */
  256.         else if ((GetTokenType(Token) == eTokenKeyword)
  257.             && (GetTokenKeywordTag(Token) == eKeywordProto))
  258.             {
  259.                 /* push token back */
  260.                 UngetToken(Scanner,Token);
  261.  
  262.                 /* parse prototype */
  263.                 Error = ParsePrototype(FunctionSymbolTableEntryOut,Scanner,SymbolTable,
  264.                     TrashTracker,LineNumberOut);
  265.                 *FunctionBodyOut = NIL; /* no code body for a prototype */
  266.                 if (Error != eCompileNoError)
  267.                     {
  268.                         return Error;
  269.                     }
  270.             }
  271.  
  272.         /* otherwise, it's an error */
  273.         else
  274.             {
  275.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  276.                 return eCompileExpectedFuncOrProto;
  277.             }
  278.  
  279.  
  280.         /* swallow the semicolon */
  281.         Token = GetNextToken(Scanner);
  282.         if (Token == NIL)
  283.             {
  284.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  285.                 return eCompileOutOfMemory;
  286.             }
  287.         if (GetTokenType(Token) != eTokenSemicolon)
  288.             {
  289.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  290.                 return eCompileExpectedSemicolon;
  291.             }
  292.  
  293.         return eCompileNoError;
  294.     }
  295.  
  296.  
  297.  
  298.  
  299. /* this parses a function declaration, returning the symbol table entry for the */
  300. /* function in *FunctionSymbolTableEntryOut and the expression for the function */
  301. /* in *FunctionBodyOut. */
  302. /*  14:   <function>         ::= func <identifier> ( <formalparamstart> ) : */
  303. /*      <type> <expr> */
  304. /* FIRST SET: */
  305. /* <function>         : {func} */
  306. /* FOLLOW SET: */
  307. /* <function>         : {;} */
  308. static CompileErrors    ParseFunction(SymbolRec** FunctionSymbolTableEntryOut,
  309.                                                 ASTExpressionRec** FunctionBodyOut,
  310.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  311.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  312.     {
  313.         TokenRec*                        Token;
  314.         TokenRec*                        FunctionName;
  315.         SymbolListRec*            FormalArgumentList;
  316.         CompileErrors                Error;
  317.         DataTypes                        ReturnType;
  318.         long                                LineNumberOfIdentifier;
  319.  
  320.         /* swallow "func" */
  321.         Token = GetNextToken(Scanner);
  322.         if (Token == NIL)
  323.             {
  324.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  325.                 return eCompileOutOfMemory;
  326.             }
  327.         if ((GetTokenType(Token) != eTokenKeyword)
  328.             || (GetTokenKeywordTag(Token) != eKeywordFunc))
  329.             {
  330.                 /* this is impossible -- we should be able to do some error checking here, */
  331.                 /* but it seems uncertain since we don't (formally) know whose calling us. */
  332.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  333.                 return eCompileExpectedFunc;
  334.             }
  335.  
  336.         /* get the identifier */
  337.         FunctionName = GetNextToken(Scanner);
  338.         if (FunctionName == NIL)
  339.             {
  340.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  341.                 return eCompileOutOfMemory;
  342.             }
  343.         if (GetTokenType(FunctionName) != eTokenIdentifier)
  344.             {
  345.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  346.                 return eCompileExpectedIdentifier;
  347.             }
  348.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  349.  
  350.         /* add the identifier to the symbol table */
  351.         *FunctionSymbolTableEntryOut = NewSymbol(TrashTracker,
  352.             GetTokenIdentifierString(FunctionName),
  353.             PtrSize(GetTokenIdentifierString(FunctionName)));
  354.         if (*FunctionSymbolTableEntryOut == NIL)
  355.             {
  356.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  357.                 return eCompileOutOfMemory;
  358.             }
  359.         switch (AddSymbolToTable(SymbolTable,*FunctionSymbolTableEntryOut))
  360.             {
  361.                 case eAddSymbolNoErr:
  362.                     break;
  363.                 case eAddSymbolAlreadyExists:
  364.                     *LineNumberOut = LineNumberOfIdentifier;
  365.                     return eCompileMultiplyDefinedIdentifier;
  366.                 case eAddSymbolNoMemory:
  367.                     *LineNumberOut = LineNumberOfIdentifier;
  368.                     return eCompileOutOfMemory;
  369.                 default:
  370.                     EXECUTE(PRERR(ForceAbort,"ParseFunction:  bad value from AddSymbolToTable"));
  371.                     break;
  372.             }
  373.  
  374.         /* create a new lexical level */
  375.         if (!IncrementSymbolTableLevel(SymbolTable))
  376.             {
  377.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  378.                 return eCompileOutOfMemory;
  379.             }
  380.  
  381.         /* swallow the open parenthesis */
  382.         Token = GetNextToken(Scanner);
  383.         if (Token == NIL)
  384.             {
  385.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  386.                 return eCompileOutOfMemory;
  387.             }
  388.         if (GetTokenType(Token) != eTokenOpenParen)
  389.             {
  390.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  391.                 return eCompileExpectedOpenParen;
  392.             }
  393.  
  394.         /* parse <formalparamstart> */
  395.         Error = ParseFormalParamStart(&FormalArgumentList,Scanner,SymbolTable,
  396.             TrashTracker,LineNumberOut);
  397.         if (Error != eCompileNoError)
  398.             {
  399.                 return Error;
  400.             }
  401.  
  402.         /* swallow the close parenthesis */
  403.         Token = GetNextToken(Scanner);
  404.         if (Token == NIL)
  405.             {
  406.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  407.                 return eCompileOutOfMemory;
  408.             }
  409.         if (GetTokenType(Token) != eTokenCloseParen)
  410.             {
  411.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  412.                 return eCompileExpectedCloseParen;
  413.             }
  414.  
  415.         /* swallow the colon */
  416.         Token = GetNextToken(Scanner);
  417.         if (Token == NIL)
  418.             {
  419.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  420.                 return eCompileOutOfMemory;
  421.             }
  422.         if (GetTokenType(Token) != eTokenColon)
  423.             {
  424.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  425.                 return eCompileExpectedColon;
  426.             }
  427.  
  428.         /* parse the return type of the function */
  429.         Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  430.         if (Error != eCompileNoError)
  431.             {
  432.                 return Error;
  433.             }
  434.  
  435.         /* store the interesting information into the symbol table entry */
  436.         SymbolBecomeFunction(*FunctionSymbolTableEntryOut,FormalArgumentList,ReturnType);
  437.  
  438.         /* parse the body of the function */
  439.         Error = ParseExpr(FunctionBodyOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  440.         if (Error != eCompileNoError)
  441.             {
  442.                 return Error;
  443.             }
  444.  
  445.         /* pop lexical level */
  446.         DecrementSymbolTableLevel(SymbolTable);
  447.  
  448.         return eCompileNoError;
  449.     }
  450.  
  451.  
  452.  
  453.  
  454. /* this parses a prototype of a function and returns a symbol table entry in */
  455. /* the *PrototypeSymbolTableEntryOut place. */
  456. /*  21:   <prototype>        ::= proto <identifier> ( <formalparamstart> ) : */
  457. /*      <type> */
  458. /* FIRST SET: */
  459. /* <prototype>        : {proto} */
  460. /* FOLLOW SET: */
  461. /*  <prototype>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  462. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  463. static CompileErrors    ParsePrototype(SymbolRec** PrototypeSymbolTableEntryOut,
  464.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  465.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  466.     {
  467.         TokenRec*                        Token;
  468.         TokenRec*                        FunctionName;
  469.         long                                LineNumberOfIdentifier;
  470.         CompileErrors                Error;
  471.         SymbolListRec*            FormalArgumentList;
  472.         DataTypes                        ReturnType;
  473.  
  474.         /* swallow "proto" */
  475.         Token = GetNextToken(Scanner);
  476.         if (Token == NIL)
  477.             {
  478.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  479.                 return eCompileOutOfMemory;
  480.             }
  481.         if ((GetTokenType(Token) != eTokenKeyword)
  482.             || (GetTokenKeywordTag(Token) != eKeywordProto))
  483.             {
  484.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  485.                 return eCompileExpectedFunc;
  486.             }
  487.  
  488.         /* get the identifier */
  489.         FunctionName = GetNextToken(Scanner);
  490.         if (FunctionName == NIL)
  491.             {
  492.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  493.                 return eCompileOutOfMemory;
  494.             }
  495.         if (GetTokenType(FunctionName) != eTokenIdentifier)
  496.             {
  497.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  498.                 return eCompileExpectedIdentifier;
  499.             }
  500.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  501.  
  502.         /* add the identifier to the symbol table */
  503.         *PrototypeSymbolTableEntryOut = NewSymbol(TrashTracker,
  504.             GetTokenIdentifierString(FunctionName),
  505.             PtrSize(GetTokenIdentifierString(FunctionName)));
  506.         if (*PrototypeSymbolTableEntryOut == NIL)
  507.             {
  508.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  509.                 return eCompileOutOfMemory;
  510.             }
  511.         switch (AddSymbolToTable(SymbolTable,*PrototypeSymbolTableEntryOut))
  512.             {
  513.                 case eAddSymbolNoErr:
  514.                     break;
  515.                 case eAddSymbolAlreadyExists:
  516.                     *LineNumberOut = LineNumberOfIdentifier;
  517.                     return eCompileMultiplyDefinedIdentifier;
  518.                 case eAddSymbolNoMemory:
  519.                     *LineNumberOut = LineNumberOfIdentifier;
  520.                     return eCompileOutOfMemory;
  521.                 default:
  522.                     EXECUTE(PRERR(ForceAbort,"ParsePrototype:  bad value from AddSymbolToTable"));
  523.                     break;
  524.             }
  525.  
  526.         /* create a new lexical level */
  527.         if (!IncrementSymbolTableLevel(SymbolTable))
  528.             {
  529.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  530.                 return eCompileOutOfMemory;
  531.             }
  532.  
  533.         /* swallow the open parenthesis */
  534.         Token = GetNextToken(Scanner);
  535.         if (Token == NIL)
  536.             {
  537.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  538.                 return eCompileOutOfMemory;
  539.             }
  540.         if (GetTokenType(Token) != eTokenOpenParen)
  541.             {
  542.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  543.                 return eCompileExpectedOpenParen;
  544.             }
  545.  
  546.         /* parse <formalparamstart> */
  547.         Error = ParseFormalParamStart(&FormalArgumentList,Scanner,SymbolTable,
  548.             TrashTracker,LineNumberOut);
  549.         if (Error != eCompileNoError)
  550.             {
  551.                 return Error;
  552.             }
  553.  
  554.         /* swallow the close parenthesis */
  555.         Token = GetNextToken(Scanner);
  556.         if (Token == NIL)
  557.             {
  558.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  559.                 return eCompileOutOfMemory;
  560.             }
  561.         if (GetTokenType(Token) != eTokenCloseParen)
  562.             {
  563.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  564.                 return eCompileExpectedCloseParen;
  565.             }
  566.  
  567.         /* swallow the colon */
  568.         Token = GetNextToken(Scanner);
  569.         if (Token == NIL)
  570.             {
  571.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  572.                 return eCompileOutOfMemory;
  573.             }
  574.         if (GetTokenType(Token) != eTokenColon)
  575.             {
  576.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  577.                 return eCompileExpectedColon;
  578.             }
  579.  
  580.         /* parse the return type of the function */
  581.         Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  582.         if (Error != eCompileNoError)
  583.             {
  584.                 return Error;
  585.             }
  586.  
  587.         /* store the interesting information into the symbol table entry */
  588.         SymbolBecomeFunction(*PrototypeSymbolTableEntryOut,FormalArgumentList,ReturnType);
  589.  
  590.         /* pop lexical level */
  591.         DecrementSymbolTableLevel(SymbolTable);
  592.  
  593.         return eCompileNoError;
  594.     }
  595.  
  596.  
  597.  
  598.  
  599. /* this parses an argument list.  the argument list may be empty, in which case */
  600. /* the empty list (NIL) is returned in *FormalArgListOut. */
  601. /*  15:   <formalparamstart> ::= <formalparamlist> */
  602. /*  16:                      ::=  */
  603. /* FIRST SET: */
  604. /* <formalparamstart> : {<identifier>, <formalparamlist>, <formalarg>} */
  605. /* FOLLOW SET: */
  606. /* <formalparamstart> : {)} */
  607. static CompileErrors    ParseFormalParamStart(SymbolListRec** FormalArgListOut,
  608.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  609.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  610.     {
  611.         TokenRec*                        Token;
  612.  
  613.         /* get a token so we can lookahead */
  614.         Token = GetNextToken(Scanner);
  615.         if (Token == NIL)
  616.             {
  617.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  618.                 return eCompileOutOfMemory;
  619.             }
  620.  
  621.         /* if it's a paren, then we abort */
  622.         if (GetTokenType(Token) == eTokenCloseParen)
  623.             {
  624.                 /* stuff it back */
  625.                 UngetToken(Scanner,Token);
  626.  
  627.                 /* we want to return the empty list since argument list is empty */
  628.                 *FormalArgListOut = NIL;
  629.  
  630.                 return eCompileNoError;
  631.             }
  632.  
  633.         /* stuff it back */
  634.         UngetToken(Scanner,Token);
  635.  
  636.         /* it really is something, so parse it */
  637.         return ParseFormalParamList(FormalArgListOut,Scanner,SymbolTable,TrashTracker,
  638.             LineNumberOut);
  639.     }
  640.  
  641.  
  642.  
  643.  
  644. /* this function parses a type and returns the corresponding enumeration value */
  645. /* in *TypeOut. */
  646. /*   3:   <type>             ::= void */
  647. /*   4:                      ::= bool */
  648. /*   5:                      ::= int */
  649. /*   6:                      ::= single */
  650. /*   7:                      ::= double */
  651. /*   8:                      ::= fixed */
  652. /*   9:                      ::= boolarray */
  653. /*  10:                      ::= intarray */
  654. /*  11:                      ::= singlearray */
  655. /*  12:                      ::= doublearray */
  656. /*  13:                      ::= fixedarray */
  657. /* FIRST SET: */
  658. /* <type>             : {void, bool, int, single, double, fixed, boolarray, */
  659. /*      intarray, singlearray, doublearray, fixedarray} */
  660. /* FOLLOW SET: */
  661. /*  <type>             : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  662. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, cos, */
  663. /*       tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, if, */
  664. /*       then, else, elseif, while, until, do, resize, to, error, true, */
  665. /*       false, set, (, ), CLOSEBRACKET, ,, :=, ;, -, EQ, <prototype>, <expr>, */
  666. /*       <formalargtail>, <vartail>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, */
  667. /*       <unary_oper>, <expr7>, <expr8>, <actualtail>, <iftail>, <whileloop>, */
  668. /*       <loopwhileuntil>, <untilloop>, <exprlisttail>} */
  669. static CompileErrors    ParseType(DataTypes* TypeOut, ScannerRec* Scanner,
  670.                                                 long* LineNumberOut)
  671.     {
  672.         TokenRec*                        Token;
  673.  
  674.         /* get the word */
  675.         Token = GetNextToken(Scanner);
  676.         if (Token == NIL)
  677.             {
  678.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  679.                 return eCompileOutOfMemory;
  680.             }
  681.  
  682.         /* make sure it's a keyword */
  683.         if (GetTokenType(Token) != eTokenKeyword)
  684.             {
  685.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  686.                 return eCompileExpectedTypeSpecifier;
  687.             }
  688.  
  689.         /* do the decoding */
  690.         switch (GetTokenKeywordTag(Token))
  691.             {
  692.                 default:
  693.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  694.                     return eCompileExpectedTypeSpecifier;
  695.                 case eKeywordVoid:
  696.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  697.                     return eCompileVoidExpressionIsNotAllowed;
  698.                 case eKeywordBool:
  699.                     *TypeOut = eBoolean;
  700.                     break;
  701.                 case eKeywordInt:
  702.                     *TypeOut = eInteger;
  703.                     break;
  704.                 case eKeywordSingle:
  705.                     *TypeOut = eFloat;
  706.                     break;
  707.                 case eKeywordDouble:
  708.                     *TypeOut = eDouble;
  709.                     break;
  710.                 case eKeywordFixed:
  711.                     *TypeOut = eFixed;
  712.                     break;
  713.                 case eKeywordBoolarray:
  714.                     *TypeOut = eArrayOfBoolean;
  715.                     break;
  716.                 case eKeywordIntarray:
  717.                     *TypeOut = eArrayOfInteger;
  718.                     break;
  719.                 case eKeywordSinglearray:
  720.                     *TypeOut = eArrayOfFloat;
  721.                     break;
  722.                 case eKeywordDoublearray:
  723.                     *TypeOut = eArrayOfDouble;
  724.                     break;
  725.                 case eKeywordFixedarray:
  726.                     *TypeOut = eArrayOfFixed;
  727.                     break;
  728.             }
  729.  
  730.         return eCompileNoError;
  731.     }
  732.  
  733.  
  734.  
  735.  
  736. /*   26:   <expr>             ::= <expr2> */
  737. /*  109:   <expr>             ::= if <ifrest> */
  738. /*  114:   <expr>             ::= <whileloop> */
  739. /*  115:                      ::= do <expr> <loopwhileuntil> */
  740. /*  116:                      ::= <untilloop> */
  741. /*  121:   <expr>             ::= set <expr> := <expr> */
  742. /*  125:   <expr>             ::= resize <expr> to <expr> */
  743. /*  126:                      ::= error <string> resumable <expr> */
  744. /*  XXX:                      ::= getsampleleft <string> */
  745. /*  XXX:                      ::= getsampleright <string> */
  746. /*  XXX:                      ::= getsample <string> */
  747. /*  XXX:                      ::= getwavenumframes <string> */
  748. /*  XXX:                      ::= getwavenumtables <string> */
  749. /*  XXX:                      ::= getwavedata <string> */
  750. /*  XXX:                      ::= print (<string> | <expr>) */
  751. /* FIRST SET: */
  752. /*  <expr>             : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  753. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, cos, */
  754. /*       tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, if, */
  755. /*       while, until, do, resize, error, true, false, set, (, -, */
  756. /*       <prototype>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, */
  757. /*       <expr7>, <expr8>, <whileloop>, <untilloop>} */
  758. /* FOLLOW SET: */
  759. /*  <expr>             : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  760. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  761. CompileErrors                    ParseExpr(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  762.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  763.                                                 long* LineNumberOut)
  764.     {
  765.         TokenRec*                        Token;
  766.         long                                LineNumberForFirstToken;
  767.  
  768.         CheckPtrExistence(Scanner);
  769.         CheckPtrExistence(SymbolTable);
  770.         CheckPtrExistence(TrashTracker);
  771.  
  772.         /* get the first token to be gotten */
  773.         Token = GetNextToken(Scanner);
  774.         LineNumberForFirstToken = GetCurrentLineNumber(Scanner);
  775.         if (Token == NIL)
  776.             {
  777.                 *LineNumberOut = LineNumberForFirstToken;
  778.                 return eCompileOutOfMemory;
  779.             }
  780.  
  781.         /* see what action should be taken */
  782.         switch (GetTokenType(Token))
  783.             {
  784.                 default:
  785.                     UngetToken(Scanner,Token);
  786.                     return ParseExpr2(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  787.                         LineNumberOut);
  788.  
  789.                 case eTokenKeyword:
  790.                     switch (GetTokenKeywordTag(Token))
  791.                         {
  792.                             default:
  793.                                 UngetToken(Scanner,Token);
  794.                                 return ParseExpr2(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  795.                                     LineNumberOut);
  796.  
  797.                             /*  109:   <expr>             ::= if <ifrest> */
  798.                             case eKeywordIf:
  799.                                 return ParseIfRest(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  800.                                     LineNumberOut);
  801.  
  802.                             /*  114:   <expr>             ::= <whileloop> */
  803.                             /* FIRST SET: */
  804.                             /*  <whileloop>        : {while} */
  805.                             case eKeywordWhile:
  806.                                 UngetToken(Scanner,Token);
  807.                                 return ParseWhileLoop(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  808.                                     LineNumberOut);
  809.  
  810.                             /*  115:                      ::= do <expr> <loopwhileuntil> */
  811.                             case eKeywordDo:
  812.                                 {
  813.                                     ASTExpressionRec*        BodyExpression;
  814.                                     CompileErrors                Error;
  815.  
  816.                                     Error = ParseExpr(&BodyExpression,Scanner,SymbolTable,
  817.                                         TrashTracker,LineNumberOut);
  818.                                     if (Error != eCompileNoError)
  819.                                         {
  820.                                             return Error;
  821.                                         }
  822.  
  823.                                     /* parse the rest of it */
  824.                                     return ParseLoopWhileUntil(ExpressionOut,BodyExpression,Scanner,
  825.                                         SymbolTable,TrashTracker,LineNumberOut,LineNumberForFirstToken);
  826.                                 }
  827.  
  828.                             /*  116:                      ::= <untilloop> */
  829.                             /* FIRST SET */
  830.                             /*  <untilloop>        : {until} */
  831.                             case eKeywordUntil:
  832.                                 UngetToken(Scanner,Token);
  833.                                 return ParseUntilLoop(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  834.                                     LineNumberOut);
  835.  
  836.                             /*  121:   <expr>             ::= set <expr> := <expr> */
  837.                             case eKeywordSet:
  838.                                 {
  839.                                     ASTExpressionRec*        LValue;
  840.                                     ASTExpressionRec*        RValue;
  841.                                     CompileErrors                Error;
  842.                                     ASTAssignRec*                TotalAssignment;
  843.  
  844.                                     Error = ParseExpr(&LValue,Scanner,SymbolTable,TrashTracker,
  845.                                         LineNumberOut);
  846.                                     if (Error != eCompileNoError)
  847.                                         {
  848.                                             return Error;
  849.                                         }
  850.  
  851.                                     /* swallow the colon-equals */
  852.                                     Token = GetNextToken(Scanner);
  853.                                     if (Token == NIL)
  854.                                         {
  855.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  856.                                             return eCompileOutOfMemory;
  857.                                         }
  858.                                     if (GetTokenType(Token) != eTokenColonEqual)
  859.                                         {
  860.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  861.                                             return eCompileExpectedColonEqual;
  862.                                         }
  863.  
  864.                                     Error = ParseExpr(&RValue,Scanner,SymbolTable,TrashTracker,
  865.                                         LineNumberOut);
  866.                                     if (Error != eCompileNoError)
  867.                                         {
  868.                                             return Error;
  869.                                         }
  870.  
  871.                                     TotalAssignment = NewAssignment(LValue,RValue,TrashTracker,
  872.                                         LineNumberForFirstToken);
  873.                                     if (TotalAssignment == NIL)
  874.                                         {
  875.                                             *LineNumberOut = LineNumberForFirstToken;
  876.                                             return eCompileOutOfMemory;
  877.                                         }
  878.  
  879.                                     *ExpressionOut = NewExprAssignment(TotalAssignment,TrashTracker,
  880.                                         LineNumberForFirstToken);
  881.                                     if (*ExpressionOut == NIL)
  882.                                         {
  883.                                             *LineNumberOut = LineNumberForFirstToken;
  884.                                             return eCompileOutOfMemory;
  885.                                         }
  886.  
  887.                                     return eCompileNoError;
  888.                                 }
  889.  
  890.                             /*  125:   <expr>             ::= resize <expr> to <expr> */
  891.                             case eKeywordResize:
  892.                                 {
  893.                                     ASTExpressionRec*        ArrayGenerator;
  894.                                     ASTExpressionRec*        NewSizeExpression;
  895.                                     CompileErrors                Error;
  896.                                     ASTBinaryOpRec*            BinaryOperator;
  897.  
  898.                                     Error = ParseExpr(&ArrayGenerator,Scanner,SymbolTable,TrashTracker,
  899.                                         LineNumberOut);
  900.                                     if (Error != eCompileNoError)
  901.                                         {
  902.                                             return Error;
  903.                                         }
  904.  
  905.                                     /* swallow the to */
  906.                                     Token = GetNextToken(Scanner);
  907.                                     if (Token == NIL)
  908.                                         {
  909.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  910.                                             return eCompileOutOfMemory;
  911.                                         }
  912.                                     if ((GetTokenType(Token) != eTokenKeyword)
  913.                                         || (GetTokenKeywordTag(Token) != eKeywordTo))
  914.                                         {
  915.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  916.                                             return eCompileExpectedTo;
  917.                                         }
  918.  
  919.                                     Error = ParseExpr(&NewSizeExpression,Scanner,SymbolTable,TrashTracker,
  920.                                         LineNumberOut);
  921.                                     if (Error != eCompileNoError)
  922.                                         {
  923.                                             return Error;
  924.                                         }
  925.  
  926.                                     BinaryOperator = NewBinaryOperator(eBinaryResizeArray,ArrayGenerator,
  927.                                         NewSizeExpression,TrashTracker,LineNumberForFirstToken);
  928.                                     if (BinaryOperator == NIL)
  929.                                         {
  930.                                             *LineNumberOut = LineNumberForFirstToken;
  931.                                             return eCompileOutOfMemory;
  932.                                         }
  933.  
  934.                                     *ExpressionOut = NewExprBinaryOperator(BinaryOperator,TrashTracker,
  935.                                         LineNumberForFirstToken);
  936.                                     if (*ExpressionOut == NIL)
  937.                                         {
  938.                                             *LineNumberOut = LineNumberForFirstToken;
  939.                                             return eCompileOutOfMemory;
  940.                                         }
  941.  
  942.                                     return eCompileNoError;
  943.                                 }
  944.  
  945.                             /*  126:                      ::= error <string> resumable <expr> */
  946.                             case eKeywordError:
  947.                                 {
  948.                                     TokenRec*                        MessageString;
  949.                                     ASTExpressionRec*        ResumableCondition;
  950.                                     CompileErrors                Error;
  951.                                     ASTErrorFormRec*        ErrorForm;
  952.  
  953.                                     MessageString = GetNextToken(Scanner);
  954.                                     if (MessageString == NIL)
  955.                                         {
  956.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  957.                                             return eCompileOutOfMemory;
  958.                                         }
  959.                                     if (GetTokenType(MessageString) != eTokenString)
  960.                                         {
  961.                                             *LineNumberOut = LineNumberForFirstToken;
  962.                                             return eCompileExpectedStringLiteral;
  963.                                         }
  964.  
  965.                                     /* swallow the resumable */
  966.                                     Token = GetNextToken(Scanner);
  967.                                     if (Token == NIL)
  968.                                         {
  969.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  970.                                             return eCompileOutOfMemory;
  971.                                         }
  972.                                     if ((GetTokenType(Token) != eTokenKeyword)
  973.                                         || (GetTokenKeywordTag(Token) != eKeywordResumable))
  974.                                         {
  975.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  976.                                             return eCompileExpectedResumable;
  977.                                         }
  978.  
  979.                                     Error = ParseExpr(&ResumableCondition,Scanner,SymbolTable,
  980.                                         TrashTracker,LineNumberOut);
  981.                                     if (Error != eCompileNoError)
  982.                                         {
  983.                                             return Error;
  984.                                         }
  985.  
  986.                                     ErrorForm = NewErrorForm(ResumableCondition,
  987.                                         GetTokenStringValue(MessageString),TrashTracker,
  988.                                         LineNumberForFirstToken);
  989.                                     if (ErrorForm == NIL)
  990.                                         {
  991.                                             *LineNumberOut = LineNumberForFirstToken;
  992.                                             return eCompileOutOfMemory;
  993.                                         }
  994.  
  995.                                     *ExpressionOut = NewExprErrorForm(ErrorForm,TrashTracker,
  996.                                         LineNumberForFirstToken);
  997.                                     if (*ExpressionOut == NIL)
  998.                                         {
  999.                                             *LineNumberOut = LineNumberForFirstToken;
  1000.                                             return eCompileOutOfMemory;
  1001.                                         }
  1002.  
  1003.                                     return eCompileNoError;
  1004.                                 }
  1005.  
  1006.                             /*  XXX:                      ::= getsampleleft <string> */
  1007.                             case eKeywordGetsampleleft:
  1008.                                 {
  1009.                                     ASTWaveGetterRec*        WaveGetterThang;
  1010.  
  1011.                                     Token = GetNextToken(Scanner);
  1012.                                     if (Token == NIL)
  1013.                                         {
  1014.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1015.                                             return eCompileOutOfMemory;
  1016.                                         }
  1017.                                     if (GetTokenType(Token) != eTokenString)
  1018.                                         {
  1019.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1020.                                             return eCompileExpectedStringLiteral;
  1021.                                         }
  1022.  
  1023.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1024.                                         eWaveGetterSampleLeft,TrashTracker,GetCurrentLineNumber(Scanner));
  1025.                                     if (WaveGetterThang == NIL)
  1026.                                         {
  1027.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1028.                                             return eCompileOutOfMemory;
  1029.                                         }
  1030.  
  1031.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1032.                                         GetCurrentLineNumber(Scanner));
  1033.                                     if (*ExpressionOut == NIL)
  1034.                                         {
  1035.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1036.                                             return eCompileOutOfMemory;
  1037.                                         }
  1038.  
  1039.                                     return eCompileNoError;
  1040.                                 }
  1041.  
  1042.                             /*  XXX:                      ::= getsampleright <string> */
  1043.                             case eKeywordGetsampleright:
  1044.                                 {
  1045.                                     ASTWaveGetterRec*        WaveGetterThang;
  1046.  
  1047.                                     Token = GetNextToken(Scanner);
  1048.                                     if (Token == NIL)
  1049.                                         {
  1050.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1051.                                             return eCompileOutOfMemory;
  1052.                                         }
  1053.                                     if (GetTokenType(Token) != eTokenString)
  1054.                                         {
  1055.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1056.                                             return eCompileExpectedStringLiteral;
  1057.                                         }
  1058.  
  1059.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1060.                                         eWaveGetterSampleRight,TrashTracker,GetCurrentLineNumber(Scanner));
  1061.                                     if (WaveGetterThang == NIL)
  1062.                                         {
  1063.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1064.                                             return eCompileOutOfMemory;
  1065.                                         }
  1066.  
  1067.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1068.                                         GetCurrentLineNumber(Scanner));
  1069.                                     if (*ExpressionOut == NIL)
  1070.                                         {
  1071.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1072.                                             return eCompileOutOfMemory;
  1073.                                         }
  1074.  
  1075.                                     return eCompileNoError;
  1076.                                 }
  1077.  
  1078.                             /*  XXX:                      ::= getsample <string> */
  1079.                             case eKeywordGetsample:
  1080.                                 {
  1081.                                     ASTWaveGetterRec*        WaveGetterThang;
  1082.  
  1083.                                     Token = GetNextToken(Scanner);
  1084.                                     if (Token == NIL)
  1085.                                         {
  1086.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1087.                                             return eCompileOutOfMemory;
  1088.                                         }
  1089.                                     if (GetTokenType(Token) != eTokenString)
  1090.                                         {
  1091.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1092.                                             return eCompileExpectedStringLiteral;
  1093.                                         }
  1094.  
  1095.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1096.                                         eWaveGetterSampleMono,TrashTracker,GetCurrentLineNumber(Scanner));
  1097.                                     if (WaveGetterThang == NIL)
  1098.                                         {
  1099.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1100.                                             return eCompileOutOfMemory;
  1101.                                         }
  1102.  
  1103.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1104.                                         GetCurrentLineNumber(Scanner));
  1105.                                     if (*ExpressionOut == NIL)
  1106.                                         {
  1107.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1108.                                             return eCompileOutOfMemory;
  1109.                                         }
  1110.  
  1111.                                     return eCompileNoError;
  1112.                                 }
  1113.  
  1114.                             /*  XXX:                      ::= getwavenumframes <string> */
  1115.                             case eKeywordGetwavenumframes:
  1116.                                 {
  1117.                                     ASTWaveGetterRec*        WaveGetterThang;
  1118.  
  1119.                                     Token = GetNextToken(Scanner);
  1120.                                     if (Token == NIL)
  1121.                                         {
  1122.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1123.                                             return eCompileOutOfMemory;
  1124.                                         }
  1125.                                     if (GetTokenType(Token) != eTokenString)
  1126.                                         {
  1127.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1128.                                             return eCompileExpectedStringLiteral;
  1129.                                         }
  1130.  
  1131.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1132.                                         eWaveGetterWaveFrames,TrashTracker,GetCurrentLineNumber(Scanner));
  1133.                                     if (WaveGetterThang == NIL)
  1134.                                         {
  1135.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1136.                                             return eCompileOutOfMemory;
  1137.                                         }
  1138.  
  1139.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1140.                                         GetCurrentLineNumber(Scanner));
  1141.                                     if (*ExpressionOut == NIL)
  1142.                                         {
  1143.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1144.                                             return eCompileOutOfMemory;
  1145.                                         }
  1146.  
  1147.                                     return eCompileNoError;
  1148.                                 }
  1149.  
  1150.                             /*  XXX:                      ::= getwavenumtables <string> */
  1151.                             case eKeywordGetwavenumtables:
  1152.                                 {
  1153.                                     ASTWaveGetterRec*        WaveGetterThang;
  1154.  
  1155.                                     Token = GetNextToken(Scanner);
  1156.                                     if (Token == NIL)
  1157.                                         {
  1158.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1159.                                             return eCompileOutOfMemory;
  1160.                                         }
  1161.                                     if (GetTokenType(Token) != eTokenString)
  1162.                                         {
  1163.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1164.                                             return eCompileExpectedStringLiteral;
  1165.                                         }
  1166.  
  1167.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1168.                                         eWaveGetterWaveTables,TrashTracker,GetCurrentLineNumber(Scanner));
  1169.                                     if (WaveGetterThang == NIL)
  1170.                                         {
  1171.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1172.                                             return eCompileOutOfMemory;
  1173.                                         }
  1174.  
  1175.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1176.                                         GetCurrentLineNumber(Scanner));
  1177.                                     if (*ExpressionOut == NIL)
  1178.                                         {
  1179.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1180.                                             return eCompileOutOfMemory;
  1181.                                         }
  1182.  
  1183.                                     return eCompileNoError;
  1184.                                 }
  1185.  
  1186.                             /*  XXX:                      ::= getwavedata <string> */
  1187.                             case eKeywordGetwavedata:
  1188.                                 {
  1189.                                     ASTWaveGetterRec*        WaveGetterThang;
  1190.  
  1191.                                     Token = GetNextToken(Scanner);
  1192.                                     if (Token == NIL)
  1193.                                         {
  1194.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1195.                                             return eCompileOutOfMemory;
  1196.                                         }
  1197.                                     if (GetTokenType(Token) != eTokenString)
  1198.                                         {
  1199.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1200.                                             return eCompileExpectedStringLiteral;
  1201.                                         }
  1202.  
  1203.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1204.                                         eWaveGetterWaveArray,TrashTracker,GetCurrentLineNumber(Scanner));
  1205.                                     if (WaveGetterThang == NIL)
  1206.                                         {
  1207.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1208.                                             return eCompileOutOfMemory;
  1209.                                         }
  1210.  
  1211.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1212.                                         GetCurrentLineNumber(Scanner));
  1213.                                     if (*ExpressionOut == NIL)
  1214.                                         {
  1215.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1216.                                             return eCompileOutOfMemory;
  1217.                                         }
  1218.  
  1219.                                     return eCompileNoError;
  1220.                                 }
  1221.  
  1222.                             /*  XXX:                      ::= print (<string> | <expr>) */
  1223.                             case eKeywordPrint:
  1224.                                 Token = GetNextToken(Scanner);
  1225.                                 if (Token == NIL)
  1226.                                     {
  1227.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  1228.                                         return eCompileOutOfMemory;
  1229.                                     }
  1230.                                 if (GetTokenType(Token) == eTokenString)
  1231.                                     {
  1232.                                         ASTPrintStringRec*    PrintString;
  1233.  
  1234.                                         /* print string literal part */
  1235.                                         PrintString = NewPrintString(GetTokenStringValue(Token),
  1236.                                             TrashTracker,LineNumberForFirstToken);
  1237.                                         if (PrintString == NIL)
  1238.                                             {
  1239.                                                 *LineNumberOut = LineNumberForFirstToken;
  1240.                                                 return eCompileOutOfMemory;
  1241.                                             }
  1242.                                         *ExpressionOut = NewExprPrintString(PrintString,TrashTracker,
  1243.                                             LineNumberForFirstToken);
  1244.                                         if (*ExpressionOut == NIL)
  1245.                                             {
  1246.                                                 *LineNumberOut = LineNumberForFirstToken;
  1247.                                                 return eCompileOutOfMemory;
  1248.                                             }
  1249.                                     }
  1250.                                  else
  1251.                                     {
  1252.                                         ASTPrintExprRec*        PrintExpr;
  1253.                                         ASTExpressionRec*        Operand;
  1254.                                         CompileErrors                Error;
  1255.  
  1256.                                         /* print expression part */
  1257.                                         UngetToken(Scanner,Token);
  1258.                                         Error = ParseExpr(&Operand,Scanner,SymbolTable,
  1259.                                             TrashTracker,LineNumberOut);
  1260.                                         if (Error != eCompileNoError)
  1261.                                             {
  1262.                                                 return Error;
  1263.                                             }
  1264.                                         PrintExpr = NewPrintExpr(Operand,TrashTracker,
  1265.                                             LineNumberForFirstToken);
  1266.                                         if (PrintExpr == NIL)
  1267.                                             {
  1268.                                                 *LineNumberOut = LineNumberForFirstToken;
  1269.                                                 return eCompileOutOfMemory;
  1270.                                             }
  1271.                                         *ExpressionOut = NewExprPrintExpr(PrintExpr,TrashTracker,
  1272.                                             LineNumberForFirstToken);
  1273.                                         if (*ExpressionOut == NIL)
  1274.                                             {
  1275.                                                 *LineNumberOut = LineNumberForFirstToken;
  1276.                                                 return eCompileOutOfMemory;
  1277.                                             }
  1278.                                     }
  1279.                                 return eCompileNoError;
  1280.                         }
  1281.             }
  1282.         EXECUTE(PRERR(ForceAbort,"ParseExpr:  control reached end of function"));
  1283.     }
  1284.  
  1285.  
  1286.  
  1287.  
  1288. /*   17:   <formalparamlist>  ::= <formalarg> <formalargtail>  */
  1289. /* FIRST SET: */
  1290. /*  <formalparamlist>  : {<identifier>, <formalarg>} */
  1291. /* FOLLOW SET: */
  1292. /*  <formalparamlist>  : {)} */
  1293. static CompileErrors    ParseFormalParamList(SymbolListRec** FormalArgListOut,
  1294.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1295.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1296.     {
  1297.         CompileErrors                Error;
  1298.         SymbolRec*                    FormalArgOut;
  1299.         SymbolListRec*            ListTail;
  1300.  
  1301.         CheckPtrExistence(Scanner);
  1302.         CheckPtrExistence(SymbolTable);
  1303.         CheckPtrExistence(TrashTracker);
  1304.  
  1305.         Error = ParseFormalArg(&FormalArgOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1306.         if (Error != eCompileNoError)
  1307.             {
  1308.                 return Error;
  1309.             }
  1310.  
  1311.         Error = ParseFormalArgTail(&ListTail,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1312.         if (Error != eCompileNoError)
  1313.             {
  1314.                 return Error;
  1315.             }
  1316.  
  1317.         *FormalArgListOut = SymbolListCons(FormalArgOut,ListTail,TrashTracker);
  1318.         if (*FormalArgListOut == NIL)
  1319.             {
  1320.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1321.                 return eCompileOutOfMemory;
  1322.             }
  1323.  
  1324.         return eCompileNoError;
  1325.     }
  1326.  
  1327.  
  1328.  
  1329.  
  1330. /*  117:   <whileloop>        ::= while <expr> do <expr> */
  1331. /* FIRST SET: */
  1332. /*  <whileloop>        : {while} */
  1333. /* FOLLOW SET: */
  1334. /*  <whileloop>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1335. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1336. static CompileErrors    ParseWhileLoop(ASTExpressionRec** ExpressionOut,
  1337.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1338.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1339.     {
  1340.         TokenRec*                        Token;
  1341.         ASTExpressionRec*        ConditionalExpr;
  1342.         ASTExpressionRec*        BodyExpr;
  1343.         CompileErrors                Error;
  1344.         ASTLoopRec*                    WhileLoopThing;
  1345.         long                                LineNumberOfWholeForm;
  1346.  
  1347.         CheckPtrExistence(Scanner);
  1348.         CheckPtrExistence(SymbolTable);
  1349.         CheckPtrExistence(TrashTracker);
  1350.  
  1351.         LineNumberOfWholeForm = GetCurrentLineNumber(Scanner);
  1352.  
  1353.         /* munch while */
  1354.         Token = GetNextToken(Scanner);
  1355.         if (Token == NIL)
  1356.             {
  1357.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1358.                 return eCompileOutOfMemory;
  1359.             }
  1360.         if ((GetTokenType(Token) != eTokenKeyword)
  1361.             || (GetTokenKeywordTag(Token) != eKeywordWhile))
  1362.             {
  1363.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1364.                 return eCompileExpectedWhile;
  1365.             }
  1366.  
  1367.         Error = ParseExpr(&ConditionalExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1368.         if (Error != eCompileNoError)
  1369.             {
  1370.                 return Error;
  1371.             }
  1372.  
  1373.         /* munch do */
  1374.         Token = GetNextToken(Scanner);
  1375.         if (Token == NIL)
  1376.             {
  1377.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1378.                 return eCompileOutOfMemory;
  1379.             }
  1380.         if ((GetTokenType(Token) != eTokenKeyword)
  1381.             || (GetTokenKeywordTag(Token) != eKeywordDo))
  1382.             {
  1383.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1384.                 return eCompileExpectedDo;
  1385.             }
  1386.  
  1387.         Error = ParseExpr(&BodyExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1388.         if (Error != eCompileNoError)
  1389.             {
  1390.                 return Error;
  1391.             }
  1392.  
  1393.         WhileLoopThing = NewLoop(eLoopWhileDo,ConditionalExpr,BodyExpr,TrashTracker,
  1394.             LineNumberOfWholeForm);
  1395.         if (WhileLoopThing == NIL)
  1396.             {
  1397.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1398.                 return eCompileOutOfMemory;
  1399.             }
  1400.  
  1401.         *ExpressionOut = NewExprLoop(WhileLoopThing,TrashTracker,LineNumberOfWholeForm);
  1402.         if (*ExpressionOut == NIL)
  1403.             {
  1404.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1405.                 return eCompileOutOfMemory;
  1406.             }
  1407.  
  1408.         return eCompileNoError;
  1409.     }
  1410.  
  1411.  
  1412.  
  1413.  
  1414. /*  118:   <untilloop>        ::= until <expr> do <expr> */
  1415. /* FIRST SET: */
  1416. /*  <untilloop>        : {until} */
  1417. /* FOLLOW SET: */
  1418. /*  <untilloop>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1419. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1420. static CompileErrors    ParseUntilLoop(ASTExpressionRec** ExpressionOut,
  1421.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1422.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1423.     {
  1424.         TokenRec*                        Token;
  1425.         ASTExpressionRec*        ConditionalExpr;
  1426.         ASTExpressionRec*        BodyExpr;
  1427.         CompileErrors                Error;
  1428.         ASTLoopRec*                    UntilLoopThing;
  1429.         long                                LineNumberOfWholeForm;
  1430.  
  1431.         CheckPtrExistence(Scanner);
  1432.         CheckPtrExistence(SymbolTable);
  1433.         CheckPtrExistence(TrashTracker);
  1434.  
  1435.         LineNumberOfWholeForm = GetCurrentLineNumber(Scanner);
  1436.  
  1437.         /* munch until */
  1438.         Token = GetNextToken(Scanner);
  1439.         if (Token == NIL)
  1440.             {
  1441.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1442.                 return eCompileOutOfMemory;
  1443.             }
  1444.         if ((GetTokenType(Token) != eTokenKeyword)
  1445.             || (GetTokenKeywordTag(Token) != eKeywordUntil))
  1446.             {
  1447.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1448.                 return eCompileExpectedUntil;
  1449.             }
  1450.  
  1451.         Error = ParseExpr(&ConditionalExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1452.         if (Error != eCompileNoError)
  1453.             {
  1454.                 return Error;
  1455.             }
  1456.  
  1457.         /* munch do */
  1458.         Token = GetNextToken(Scanner);
  1459.         if (Token == NIL)
  1460.             {
  1461.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1462.                 return eCompileOutOfMemory;
  1463.             }
  1464.         if ((GetTokenType(Token) != eTokenKeyword)
  1465.             || (GetTokenKeywordTag(Token) != eKeywordDo))
  1466.             {
  1467.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1468.                 return eCompileExpectedDo;
  1469.             }
  1470.  
  1471.         Error = ParseExpr(&BodyExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1472.         if (Error != eCompileNoError)
  1473.             {
  1474.                 return Error;
  1475.             }
  1476.  
  1477.         UntilLoopThing = NewLoop(eLoopUntilDo,ConditionalExpr,BodyExpr,TrashTracker,
  1478.             LineNumberOfWholeForm);
  1479.         if (UntilLoopThing == NIL)
  1480.             {
  1481.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1482.                 return eCompileOutOfMemory;
  1483.             }
  1484.  
  1485.         *ExpressionOut = NewExprLoop(UntilLoopThing,TrashTracker,LineNumberOfWholeForm);
  1486.         if (*ExpressionOut == NIL)
  1487.             {
  1488.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1489.                 return eCompileOutOfMemory;
  1490.             }
  1491.  
  1492.         return eCompileNoError;
  1493.     }
  1494.  
  1495.  
  1496.  
  1497.  
  1498. /*   24:   <vartail>          ::= EQ <expr> */
  1499. /*   25:                      ::= ( <expr> ) */
  1500. /* FIRST SET: */
  1501. /*  <vartail>          : {(, EQ} */
  1502. /* FOLLOW SET: */
  1503. /*  <vartail>          : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1504. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1505. static CompileErrors    ParseVarTail(ASTExpressionRec** ExpressionOut,
  1506.                                                 TokenRec* VariableName, long VariableDeclLine,
  1507.                                                 DataTypes VariableType, ScannerRec* Scanner,
  1508.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1509.                                                 long* LineNumberOut)
  1510.     {
  1511.         TokenRec*                        Token;
  1512.         SymbolRec*                    SymbolTableEntry;
  1513.  
  1514.         CheckPtrExistence(VariableName);
  1515.         CheckPtrExistence(Scanner);
  1516.         CheckPtrExistence(SymbolTable);
  1517.         CheckPtrExistence(TrashTracker);
  1518.  
  1519.         Token = GetNextToken(Scanner);
  1520.         if (Token == NIL)
  1521.             {
  1522.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1523.                 return eCompileOutOfMemory;
  1524.             }
  1525.  
  1526.         /* create symbol table entry */
  1527.         SymbolTableEntry = NewSymbol(TrashTracker,GetTokenIdentifierString(
  1528.             VariableName),PtrSize(GetTokenIdentifierString(VariableName)));
  1529.         if (SymbolTableEntry == NIL)
  1530.             {
  1531.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1532.                 return eCompileOutOfMemory;
  1533.             }
  1534.         SymbolBecomeVariable(SymbolTableEntry,VariableType);
  1535.  
  1536.         /* see what to do */
  1537.         switch (GetTokenType(Token))
  1538.             {
  1539.                 default:
  1540.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1541.                     return eCompileExpectedOpenParenOrEqual;
  1542.  
  1543.                 /* array declaration */
  1544.                 case eTokenOpenParen:
  1545.                     {
  1546.                         ASTExpressionRec*            ArraySizeExpression;
  1547.                         CompileErrors                    Error;
  1548.                         ASTArrayDeclRec*            ArrayConstructor;
  1549.  
  1550.                         if ((VariableType != eArrayOfBoolean) && (VariableType != eArrayOfInteger)
  1551.                             && (VariableType != eArrayOfFloat) && (VariableType != eArrayOfDouble)
  1552.                             && (VariableType != eArrayOfFixed))
  1553.                             {
  1554.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1555.                                 return eCompileArrayConstructionOnScalarType;
  1556.                             }
  1557.  
  1558.                         Error = ParseExpr(&ArraySizeExpression,Scanner,SymbolTable,TrashTracker,
  1559.                             LineNumberOut);
  1560.                         if (Error != eCompileNoError)
  1561.                             {
  1562.                                 return Error;
  1563.                             }
  1564.  
  1565.                         /* swallow the close paren */
  1566.                         Token = GetNextToken(Scanner);
  1567.                         if (Token == NIL)
  1568.                             {
  1569.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1570.                                 return eCompileOutOfMemory;
  1571.                             }
  1572.                         if (GetTokenType(Token) != eTokenCloseParen)
  1573.                             {
  1574.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1575.                                 return eCompileExpectedCloseParen;
  1576.                             }
  1577.  
  1578.                         /* build the array constructor node */
  1579.                         ArrayConstructor = NewArrayConstruction(SymbolTableEntry,
  1580.                             ArraySizeExpression,TrashTracker,VariableDeclLine);
  1581.                         if (ArrayConstructor == NIL)
  1582.                             {
  1583.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1584.                                 return eCompileOutOfMemory;
  1585.                             }
  1586.  
  1587.                         /* build AST node */
  1588.                         *ExpressionOut = NewExprArrayDecl(ArrayConstructor,TrashTracker,
  1589.                             VariableDeclLine);
  1590.                         if (*ExpressionOut == NIL)
  1591.                             {
  1592.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1593.                                 return eCompileOutOfMemory;
  1594.                             }
  1595.                     }
  1596.                     break;
  1597.  
  1598.                 /* variable construction */
  1599.                 case eTokenEqual:
  1600.                     {
  1601.                         ASTExpressionRec*            Initializer;
  1602.                         CompileErrors                    Error;
  1603.                         ASTVarDeclRec*                VariableConstructor;
  1604.  
  1605.                         Error = ParseExpr(&Initializer,Scanner,SymbolTable,TrashTracker,
  1606.                             LineNumberOut);
  1607.                         if (Error != eCompileNoError)
  1608.                             {
  1609.                                 return Error;
  1610.                             }
  1611.  
  1612.                         /* build variable thing */
  1613.                         VariableConstructor = NewVariableDeclaration(SymbolTableEntry,
  1614.                             Initializer,TrashTracker,VariableDeclLine);
  1615.                         if (VariableConstructor == NIL)
  1616.                             {
  1617.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1618.                                 return eCompileOutOfMemory;
  1619.                             }
  1620.  
  1621.                         /* encapsulate */
  1622.                         *ExpressionOut = NewExprVariableDeclaration(VariableConstructor,TrashTracker,
  1623.                             VariableDeclLine);
  1624.                         if (*ExpressionOut == NIL)
  1625.                             {
  1626.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1627.                                 return eCompileOutOfMemory;
  1628.                             }
  1629.                     }
  1630.                     break;
  1631.             }
  1632.  
  1633.         /* add the identifier to the symbol table */
  1634.         switch (AddSymbolToTable(SymbolTable,SymbolTableEntry))
  1635.             {
  1636.                 case eAddSymbolNoErr:
  1637.                     break;
  1638.                 case eAddSymbolAlreadyExists:
  1639.                     *LineNumberOut = VariableDeclLine;
  1640.                     return eCompileMultiplyDefinedIdentifier;
  1641.                 case eAddSymbolNoMemory:
  1642.                     *LineNumberOut = VariableDeclLine;
  1643.                     return eCompileOutOfMemory;
  1644.                 default:
  1645.                     EXECUTE(PRERR(ForceAbort,"ParseVarTail:  bad value from AddSymbolToTable"));
  1646.                     break;
  1647.             }
  1648.  
  1649.         return eCompileNoError;
  1650.     }
  1651.  
  1652.  
  1653.  
  1654.  
  1655. /*  110:   <ifrest>           ::= <expr> then <expr> <iftail> */
  1656. /* FIRST SET: */
  1657. /*  <ifrest>           : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  1658. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, */
  1659. /*       cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  1660. /*       if, while, until, do, resize, error, true, false, set, (, -, */
  1661. /*       <prototype>, <expr>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, */
  1662. /*       <unary_oper>, <expr7>, <expr8>, <whileloop>, <untilloop>} */
  1663. /* FOLLOW SET: */
  1664. /*  <ifrest>           : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1665. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1666. static CompileErrors    ParseIfRest(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  1667.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1668.                                                 long* LineNumberOut)
  1669.     {
  1670.         TokenRec*                        Token;
  1671.         CompileErrors                Error;
  1672.         ASTExpressionRec*        Predicate;
  1673.         ASTExpressionRec*        Consequent;
  1674.  
  1675.         CheckPtrExistence(Scanner);
  1676.         CheckPtrExistence(SymbolTable);
  1677.         CheckPtrExistence(TrashTracker);
  1678.  
  1679.         Error = ParseExpr(&Predicate,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1680.         if (Error != eCompileNoError)
  1681.             {
  1682.                 return Error;
  1683.             }
  1684.  
  1685.         /* eat the "then" */
  1686.         Token = GetNextToken(Scanner);
  1687.         if (Token == NIL)
  1688.             {
  1689.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1690.                 return eCompileOutOfMemory;
  1691.             }
  1692.         if ((GetTokenType(Token) != eTokenKeyword)
  1693.             || (GetTokenKeywordTag(Token) != eKeywordThen))
  1694.             {
  1695.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1696.                 return eCompileExpectedThen;
  1697.             }
  1698.  
  1699.         Error = ParseExpr(&Consequent,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1700.         if (Error != eCompileNoError)
  1701.             {
  1702.                 return Error;
  1703.             }
  1704.  
  1705.         return ParseIfTail(ExpressionOut,Predicate,Consequent,Scanner,SymbolTable,
  1706.             TrashTracker,LineNumberOut);
  1707.     }
  1708.  
  1709.  
  1710.  
  1711.  
  1712. /*  119:   <loopwhileuntil>   ::= while <expr> */
  1713. /*  120:                      ::= until <expr> */
  1714. /* FIRST SET: */
  1715. /*  <loopwhileuntil>   : {while, until} */
  1716. /* FOLLOW SET: */
  1717. /*  <loopwhileuntil>   : {then, else, elseif, while, until, do, to, */
  1718. /*       ), CLOSEBRACKET, ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, */
  1719. /*       <exprlisttail>} */
  1720. static CompileErrors    ParseLoopWhileUntil(ASTExpressionRec** ExpressionOut,
  1721.                                                 ASTExpressionRec* LoopBodyExpression, ScannerRec* Scanner,
  1722.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1723.                                                 long* LineNumberOut, long LineNumberOfLoop)
  1724.     {
  1725.         TokenRec*                        Token;
  1726.         LoopTypes                        LoopKind;
  1727.         ASTExpressionRec*        ConditionalExpression;
  1728.         CompileErrors                Error;
  1729.         ASTLoopRec*                    LoopThang;
  1730.  
  1731.         CheckPtrExistence(Scanner);
  1732.         CheckPtrExistence(LoopBodyExpression);
  1733.         CheckPtrExistence(SymbolTable);
  1734.         CheckPtrExistence(TrashTracker);
  1735.  
  1736.         /* see what there is to do */
  1737.         Token = GetNextToken(Scanner);
  1738.         if (Token == NIL)
  1739.             {
  1740.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1741.                 return eCompileOutOfMemory;
  1742.             }
  1743.         if (GetTokenType(Token) != eTokenKeyword)
  1744.             {
  1745.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1746.                 return eCompileExpectedWhileOrUntil;
  1747.             }
  1748.  
  1749.         switch (GetTokenKeywordTag(Token))
  1750.             {
  1751.                 default:
  1752.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1753.                     return eCompileExpectedWhileOrUntil;
  1754.  
  1755.                 case eKeywordWhile:
  1756.                     LoopKind = eLoopDoWhile;
  1757.                     break;
  1758.  
  1759.                 case eKeywordUntil:
  1760.                     LoopKind = eLoopDoUntil;
  1761.                     break;
  1762.             }
  1763.  
  1764.         Error = ParseExpr(&ConditionalExpression,Scanner,SymbolTable,TrashTracker,
  1765.             LineNumberOut);
  1766.         if (Error != eCompileNoError)
  1767.             {
  1768.                 return Error;
  1769.             }
  1770.  
  1771.         LoopThang = NewLoop(LoopKind,ConditionalExpression,LoopBodyExpression,
  1772.             TrashTracker,LineNumberOfLoop);
  1773.         if (LoopThang == NIL)
  1774.             {
  1775.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1776.                 return eCompileOutOfMemory;
  1777.             }
  1778.  
  1779.         *ExpressionOut = NewExprLoop(LoopThang,TrashTracker,LineNumberOfLoop);
  1780.         if (*ExpressionOut == NIL)
  1781.             {
  1782.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1783.                 return eCompileOutOfMemory;
  1784.             }
  1785.  
  1786.         return eCompileNoError;
  1787.     }
  1788.  
  1789.  
  1790.  
  1791.  
  1792. /*   27:   <expr2>            ::= <expr3> <expr2prime> */
  1793. /* FIRST SET: */
  1794. /*  <expr2>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  1795. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  1796. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  1797. /*       false, (, -, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  1798. /*       <expr8>} */
  1799. /* FOLLOW SET: */
  1800. /*  <expr2>            : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1801. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1802. static CompileErrors    ParseExpr2(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  1803.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1804.                                                 long* LineNumberOut)
  1805.     {
  1806.         CompileErrors                Error;
  1807.         ASTExpressionRec*        LeftHandSide;
  1808.  
  1809.         CheckPtrExistence(Scanner);
  1810.         CheckPtrExistence(SymbolTable);
  1811.         CheckPtrExistence(TrashTracker);
  1812.  
  1813.         Error = ParseExpr3(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1814.         if (Error != eCompileNoError)
  1815.             {
  1816.                 return Error;
  1817.             }
  1818.  
  1819.         return ParseExpr2Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  1820.             TrashTracker,LineNumberOut);
  1821.     }
  1822.  
  1823.  
  1824.  
  1825.  
  1826. /*   18:   <formalarg>        ::= <identifier> : <type> */
  1827. /* FIRST SET: */
  1828. /*  <formalarg>        : {<identifier>} */
  1829. /* FOLLOW SET: */
  1830. /*  <formalarg>        : {), ,, <formalargtail>} */
  1831. static CompileErrors    ParseFormalArg(SymbolRec** FormalArgOut, ScannerRec* Scanner,
  1832.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1833.                                                 long* LineNumberOut)
  1834.     {
  1835.         TokenRec*                        IdentifierName;
  1836.         TokenRec*                        Token;
  1837.         DataTypes                        Type;
  1838.         CompileErrors                Error;
  1839.         long                                LineNumberOfIdentifier;
  1840.  
  1841.         CheckPtrExistence(Scanner);
  1842.         CheckPtrExistence(SymbolTable);
  1843.         CheckPtrExistence(TrashTracker);
  1844.  
  1845.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  1846.  
  1847.         IdentifierName = GetNextToken(Scanner);
  1848.         if (IdentifierName == NIL)
  1849.             {
  1850.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1851.                 return eCompileOutOfMemory;
  1852.             }
  1853.         if (GetTokenType(IdentifierName) != eTokenIdentifier)
  1854.             {
  1855.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1856.                 return eCompileExpectedIdentifier;
  1857.             }
  1858.  
  1859.         /* swallow the colon */
  1860.         Token = GetNextToken(Scanner);
  1861.         if (Token == NIL)
  1862.             {
  1863.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1864.                 return eCompileOutOfMemory;
  1865.             }
  1866.         if (GetTokenType(Token) != eTokenColon)
  1867.             {
  1868.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1869.                 return eCompileExpectedColon;
  1870.             }
  1871.  
  1872.         Error = ParseType(&Type,Scanner,LineNumberOut);
  1873.         if (Error != eCompileNoError)
  1874.             {
  1875.                 return Error;
  1876.             }
  1877.  
  1878.         *FormalArgOut = NewSymbol(TrashTracker,GetTokenIdentifierString(IdentifierName),
  1879.             PtrSize(GetTokenIdentifierString(IdentifierName)));
  1880.         if (*FormalArgOut == NIL)
  1881.             {
  1882.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1883.                 return eCompileOutOfMemory;
  1884.             }
  1885.         SymbolBecomeVariable(*FormalArgOut,Type);
  1886.  
  1887.         switch (AddSymbolToTable(SymbolTable,*FormalArgOut))
  1888.             {
  1889.                 case eAddSymbolNoErr:
  1890.                     break;
  1891.                 case eAddSymbolAlreadyExists:
  1892.                     *LineNumberOut = LineNumberOfIdentifier;
  1893.                     return eCompileMultiplyDefinedIdentifier;
  1894.                 case eAddSymbolNoMemory:
  1895.                     *LineNumberOut = LineNumberOfIdentifier;
  1896.                     return eCompileOutOfMemory;
  1897.                 default:
  1898.                     EXECUTE(PRERR(ForceAbort,"ParseFormalArg:  bad value from AddSymbolToTable"));
  1899.                     break;
  1900.             }
  1901.  
  1902.         return eCompileNoError;
  1903.     }
  1904.  
  1905.  
  1906.  
  1907.  
  1908. /*   19:   <formalargtail>    ::= , <formalparamlist> */
  1909. /*   20:                      ::=  */
  1910. /* FIRST SET: */
  1911. /*  <formalargtail>    : {,} */
  1912. /* FOLLOW SET: */
  1913. /*  <formalargtail>    : {)} */
  1914. static CompileErrors    ParseFormalArgTail(SymbolListRec** ArgListTailOut,
  1915.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1916.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1917.     {
  1918.         TokenRec*                        Token;
  1919.  
  1920.         CheckPtrExistence(Scanner);
  1921.         CheckPtrExistence(SymbolTable);
  1922.         CheckPtrExistence(TrashTracker);
  1923.  
  1924.         Token = GetNextToken(Scanner);
  1925.         if (Token == NIL)
  1926.             {
  1927.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1928.                 return eCompileOutOfMemory;
  1929.             }
  1930.  
  1931.         switch (GetTokenType(Token))
  1932.             {
  1933.                 default:
  1934.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1935.                     return eCompileExpectedCommaOrCloseParen;
  1936.  
  1937.                 case eTokenComma:
  1938.                     return ParseFormalParamList(ArgListTailOut,Scanner,SymbolTable,TrashTracker,
  1939.                         LineNumberOut);
  1940.  
  1941.                 case eTokenCloseParen:
  1942.                     UngetToken(Scanner,Token);
  1943.                     *ArgListTailOut = NIL; /* end of list */
  1944.                     return eCompileNoError;
  1945.             }
  1946.         EXECUTE(PRERR(ForceAbort,"ParseFormalArgTail:  control reaches end of function"));
  1947.     }
  1948.  
  1949.  
  1950.  
  1951.  
  1952. /*  111:   <iftail>           ::= else <expr> */
  1953. /*  112:                      ::= elseif <ifrest> */
  1954. /*  113:                      ::=  */
  1955. /* FIRST SET: */
  1956. /*  <iftail>           : {else, elseif} */
  1957. /* FOLLOW SET: */
  1958. /*  <iftail>           : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1959. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1960. /* note that 'else' and 'elseif' are in both the first and follow set.  this is */
  1961. /* because if-then-else isn't LL(1).  we handle this by binding else to the deepest */
  1962. /* if statement. */
  1963. static CompileErrors    ParseIfTail(ASTExpressionRec** ExpressionOut,
  1964.                                                 ASTExpressionRec* Predicate, ASTExpressionRec* Consequent,
  1965.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1966.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1967.     {
  1968.         TokenRec*                        Token;
  1969.         ASTCondRec*                    Conditional;
  1970.         ASTExpressionRec*        Alternative;
  1971.         CompileErrors                Error;
  1972.  
  1973.         CheckPtrExistence(Scanner);
  1974.         CheckPtrExistence(SymbolTable);
  1975.         CheckPtrExistence(TrashTracker);
  1976.  
  1977.         /* see what the token is */
  1978.         Token = GetNextToken(Scanner);
  1979.         if (Token == NIL)
  1980.             {
  1981.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1982.                 return eCompileOutOfMemory;
  1983.             }
  1984.  
  1985.         /* do the operation */
  1986.         switch (GetTokenType(Token))
  1987.             {
  1988.                     /*  113:                      ::=  */
  1989.                 default:
  1990.                  NullificationPoint:
  1991.                     UngetToken(Scanner,Token);
  1992.                     Conditional = NewConditional(Predicate,Consequent,NIL,TrashTracker,
  1993.                         GetCurrentLineNumber(Scanner));
  1994.                     if (Conditional == NIL)
  1995.                         {
  1996.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1997.                             return eCompileOutOfMemory;
  1998.                         }
  1999.                     break;
  2000.  
  2001.                 case eTokenKeyword:
  2002.                     switch (GetTokenKeywordTag(Token))
  2003.                         {
  2004.                                 /*  113:                      ::=  */
  2005.                             default:
  2006.                                 goto NullificationPoint;
  2007.  
  2008.                                 /*  111:   <iftail>           ::= else <expr> */
  2009.                             case eKeywordElse:
  2010.                                 Error = ParseExpr(&Alternative,Scanner,SymbolTable,TrashTracker,
  2011.                                     LineNumberOut);
  2012.                                 if (Error != eCompileNoError)
  2013.                                     {
  2014.                                         return Error;
  2015.                                     }
  2016.                                 Conditional = NewConditional(Predicate,Consequent,Alternative,
  2017.                                     TrashTracker,GetCurrentLineNumber(Scanner));
  2018.                                 if (Conditional == NIL)
  2019.                                     {
  2020.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2021.                                         return eCompileOutOfMemory;
  2022.                                     }
  2023.                                 break;
  2024.  
  2025.                                 /*  112:                      ::= elseif <ifrest> */
  2026.                             case eKeywordElseif:
  2027.                                 Error = ParseIfRest(&Alternative,Scanner,SymbolTable,TrashTracker,
  2028.                                     LineNumberOut);
  2029.                                 if (Error != eCompileNoError)
  2030.                                     {
  2031.                                         return Error;
  2032.                                     }
  2033.                                 Conditional = NewConditional(Predicate,Consequent,Alternative,
  2034.                                     TrashTracker,GetCurrentLineNumber(Scanner));
  2035.                                 if (Conditional == NIL)
  2036.                                     {
  2037.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2038.                                         return eCompileOutOfMemory;
  2039.                                     }
  2040.                                 break;
  2041.                         }
  2042.                     break;
  2043.             }
  2044.  
  2045.         /* finish building expression node */
  2046.         *ExpressionOut = NewExprConditional(Conditional,TrashTracker,
  2047.             GetCurrentLineNumber(Scanner));
  2048.         if (*ExpressionOut == NIL)
  2049.             {
  2050.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2051.                 return eCompileOutOfMemory;
  2052.             }
  2053.  
  2054.         return eCompileNoError;
  2055.     }
  2056.  
  2057.  
  2058.  
  2059.  
  2060. /*   33:   <expr3>            ::= <expr4> <expr3prime> */
  2061. /* FIRST SET: */
  2062. /*  <expr3>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2063. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2064. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2065. /*       false, (, -, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2066. /* FOLLOW SET: */
  2067. /*  <expr3>            : {and, or, xor, then, else, elseif, while, until, do, */
  2068. /*       to, ), CLOSEBRACKET, ,, :=, ;, <expr2prime>, <conj_oper>, <actualtail>, */
  2069. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2070. static CompileErrors    ParseExpr3(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2071.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2072.                                                 long* LineNumberOut)
  2073.     {
  2074.         CompileErrors                Error;
  2075.         ASTExpressionRec*        LeftHandSide;
  2076.  
  2077.         CheckPtrExistence(Scanner);
  2078.         CheckPtrExistence(SymbolTable);
  2079.         CheckPtrExistence(TrashTracker);
  2080.  
  2081.         Error = ParseExpr4(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2082.         if (Error != eCompileNoError)
  2083.             {
  2084.                 return Error;
  2085.             }
  2086.  
  2087.         return ParseExpr3Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2088.             TrashTracker,LineNumberOut);
  2089.     }
  2090.  
  2091.  
  2092.  
  2093.  
  2094. /*   28:   <expr2prime>       ::= <conj_oper> <expr3> <expr2prime> */
  2095. /*   29:                      ::=  */
  2096. /* FIRST SET: */
  2097. /*  <expr2prime>       : {and, or, xor, <conj_oper>} */
  2098. /* FOLLOW SET: */
  2099. /*  <expr2prime>       : {then, else, elseif, while, until, do, to, ), */
  2100. /*       CLOSEBRACKET, ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, */
  2101. /*       <exprlisttail>} */
  2102. static CompileErrors    ParseExpr2Prime(ASTExpressionRec** ExpressionOut,
  2103.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2104.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2105.                                                 long* LineNumberOut)
  2106.     {
  2107.         TokenRec*                        Token;
  2108.         BinaryOpType                OperatorType;
  2109.         CompileErrors                Error;
  2110.         ASTExpressionRec*        RightHandSide;
  2111.         ASTBinaryOpRec*            WholeOperator;
  2112.         ASTExpressionRec*        ThisWholeNode;
  2113.  
  2114.         CheckPtrExistence(LeftHandSide);
  2115.         CheckPtrExistence(Scanner);
  2116.         CheckPtrExistence(SymbolTable);
  2117.         CheckPtrExistence(TrashTracker);
  2118.  
  2119.         Token = GetNextToken(Scanner);
  2120.         if (Token == NIL)
  2121.             {
  2122.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2123.                 return eCompileOutOfMemory;
  2124.             }
  2125.  
  2126.         switch (GetTokenType(Token))
  2127.             {
  2128.                 default:
  2129.                  NullifyPoint:
  2130.                     UngetToken(Scanner,Token);
  2131.                     *ExpressionOut = LeftHandSide;
  2132.                     return eCompileNoError;
  2133.  
  2134.                 case eTokenKeyword:
  2135.                     switch (GetTokenKeywordTag(Token))
  2136.                         {
  2137.                             default:
  2138.                                 goto NullifyPoint;
  2139.  
  2140.                             case eKeywordAnd:
  2141.                             case eKeywordOr:
  2142.                             case eKeywordXor:
  2143.                                 /* actually do the thing */
  2144.                                 UngetToken(Scanner,Token);
  2145.                                 Error = ParseConjOper(&OperatorType,Scanner,LineNumberOut);
  2146.                                 if (Error != eCompileNoError)
  2147.                                     {
  2148.                                         return Error;
  2149.                                     }
  2150.                                 Error = ParseExpr3(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2151.                                     LineNumberOut);
  2152.                                 if (Error != eCompileNoError)
  2153.                                     {
  2154.                                         return Error;
  2155.                                     }
  2156.                                 /* build the operator node */
  2157.                                 WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,
  2158.                                     RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2159.                                 if (WholeOperator == NIL)
  2160.                                     {
  2161.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2162.                                         return eCompileOutOfMemory;
  2163.                                     }
  2164.                                 ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2165.                                     GetCurrentLineNumber(Scanner));
  2166.                                 if (ThisWholeNode == NIL)
  2167.                                     {
  2168.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2169.                                         return eCompileOutOfMemory;
  2170.                                     }
  2171.                                 return ParseExpr2Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2172.                                     TrashTracker,LineNumberOut);
  2173.                         }
  2174.                     break;
  2175.             }
  2176.         EXECUTE(PRERR(ForceAbort,"ParseExpr2Prime:  control reached end of function"));
  2177.     }
  2178.  
  2179.  
  2180.  
  2181.  
  2182. /*   42:   <expr4>            ::= <expr5> <expr4prime> */
  2183. /* FIRST SET: */
  2184. /*  <expr4>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2185. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2186. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2187. /*       false, (, -, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2188. /* FOLLOW SET: */
  2189. /*  <expr4>            : {and, or, xor, then, else, elseif, while, until, do, */
  2190. /*       to, ), CLOSEBRACKET, ,, :=, ;, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, */
  2191. /*       <conj_oper>, <expr3prime>, <rel_oper>, <actualtail>, <iftail>, */
  2192. /*       <loopwhileuntil>, <exprlisttail>} */
  2193. static CompileErrors    ParseExpr4(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2194.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2195.                                                 long* LineNumberOut)
  2196.     {
  2197.         CompileErrors                Error;
  2198.         ASTExpressionRec*        LeftHandSide;
  2199.  
  2200.         CheckPtrExistence(Scanner);
  2201.         CheckPtrExistence(SymbolTable);
  2202.         CheckPtrExistence(TrashTracker);
  2203.  
  2204.         Error = ParseExpr5(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2205.         if (Error != eCompileNoError)
  2206.             {
  2207.                 return Error;
  2208.             }
  2209.  
  2210.         return ParseExpr4Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2211.             TrashTracker,LineNumberOut);
  2212.     }
  2213.  
  2214.  
  2215.  
  2216.  
  2217. /*   34:   <expr3prime>       ::= <rel_oper> <expr4> <expr3prime> */
  2218. /*   35:                      ::=  */
  2219. /* FIRST SET: */
  2220. /*  <expr3prime>       : {EQ, NEQ, LT, LTEQ, GR, GREQ, <rel_oper>} */
  2221. /* FOLLOW SET: */
  2222. /*  <expr3prime>       : {and, or, xor, then, else, elseif, while, until, */
  2223. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, <expr2prime>, <conj_oper>, */
  2224. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2225. static CompileErrors    ParseExpr3Prime(ASTExpressionRec** ExpressionOut,
  2226.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2227.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2228.                                                 long* LineNumberOut)
  2229.     {
  2230.         TokenRec*                        Token;
  2231.         BinaryOpType                OperatorType;
  2232.         CompileErrors                Error;
  2233.         ASTExpressionRec*        RightHandSide;
  2234.         ASTBinaryOpRec*            WholeOperator;
  2235.         ASTExpressionRec*        ThisWholeNode;
  2236.  
  2237.         CheckPtrExistence(LeftHandSide);
  2238.         CheckPtrExistence(Scanner);
  2239.         CheckPtrExistence(SymbolTable);
  2240.         CheckPtrExistence(TrashTracker);
  2241.  
  2242.         Token = GetNextToken(Scanner);
  2243.         if (Token == NIL)
  2244.             {
  2245.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2246.                 return eCompileOutOfMemory;
  2247.             }
  2248.  
  2249.         switch (GetTokenType(Token))
  2250.             {
  2251.                 default:
  2252.                     UngetToken(Scanner,Token);
  2253.                     *ExpressionOut = LeftHandSide;
  2254.                     return eCompileNoError;
  2255.  
  2256.                 case eTokenLessThan:
  2257.                 case eTokenLessThanOrEqual:
  2258.                 case eTokenGreaterThan:
  2259.                 case eTokenGreaterThanOrEqual:
  2260.                 case eTokenEqual:
  2261.                 case eTokenNotEqual:
  2262.                     /* actually do the thing */
  2263.                     UngetToken(Scanner,Token);
  2264.                     Error = ParseRelOper(&OperatorType,Scanner,LineNumberOut);
  2265.                     if (Error != eCompileNoError)
  2266.                         {
  2267.                             return Error;
  2268.                         }
  2269.                     Error = ParseExpr4(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2270.                         LineNumberOut);
  2271.                     if (Error != eCompileNoError)
  2272.                         {
  2273.                             return Error;
  2274.                         }
  2275.                     /* build the operator node */
  2276.                     WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,
  2277.                         RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2278.                     if (WholeOperator == NIL)
  2279.                         {
  2280.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2281.                             return eCompileOutOfMemory;
  2282.                         }
  2283.                     ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2284.                         GetCurrentLineNumber(Scanner));
  2285.                     if (ThisWholeNode == NIL)
  2286.                         {
  2287.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2288.                             return eCompileOutOfMemory;
  2289.                         }
  2290.                     return ParseExpr3Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2291.                         TrashTracker,LineNumberOut);
  2292.             }
  2293.  
  2294.         EXECUTE(PRERR(ForceAbort,"ParseExpr3Prime:  control reached end of function"));
  2295.     }
  2296.  
  2297.  
  2298.  
  2299.  
  2300. /*   30:   <conj_oper>        ::= and */
  2301. /*   31:                      ::= or */
  2302. /*   32:                      ::= xor */
  2303. /* FIRST SET: */
  2304. /*  <conj_oper>        : {and, or, xor} */
  2305. /* FOLLOW SET: */
  2306. /*  <conj_oper>        : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2307. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2308. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2309. /*       true, false, (, -, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, */
  2310. /*       <expr7>, <expr8>} */
  2311. static CompileErrors    ParseConjOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2312.                                                 long* LineNumberOut)
  2313.     {
  2314.         TokenRec*                        Token;
  2315.  
  2316.         CheckPtrExistence(Scanner);
  2317.  
  2318.         Token = GetNextToken(Scanner);
  2319.         if (Token == NIL)
  2320.             {
  2321.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2322.                 return eCompileOutOfMemory;
  2323.             }
  2324.  
  2325.         switch (GetTokenType(Token))
  2326.             {
  2327.                 default:
  2328.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2329.                     return eCompileExpectedOperatorOrStatement;
  2330.  
  2331.                 case eTokenKeyword:
  2332.                     switch (GetTokenKeywordTag(Token))
  2333.                         {
  2334.                             default:
  2335.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2336.                                 return eCompileExpectedOperatorOrStatement;
  2337.  
  2338.                             case eKeywordAnd:
  2339.                                 *OperatorOut = eBinaryAnd;
  2340.                                 return eCompileNoError;
  2341.  
  2342.                             case eKeywordOr:
  2343.                                 *OperatorOut = eBinaryOr;
  2344.                                 return eCompileNoError;
  2345.  
  2346.                             case eKeywordXor:
  2347.                                 *OperatorOut = eBinaryXor;
  2348.                                 return eCompileNoError;
  2349.                         }
  2350.                     break;
  2351.             }
  2352.         EXECUTE(PRERR(ForceAbort,"ParseConjOper:  control reached end of function"));
  2353.     }
  2354.  
  2355.  
  2356.  
  2357.  
  2358. /*   47:   <expr5>            ::= <expr6> <expr5prime> */
  2359. /* FIRST SET: */
  2360. /*  <expr5>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2361. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2362. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2363. /*       false, (, -, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2364. /* FOLLOW SET: */
  2365. /*  <expr5>            : {and, or, xor, then, else, elseif, while, until, do, */
  2366. /*       to, ), CLOSEBRACKET, ,, :=, ;, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, */
  2367. /*       <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <expr4prime>, */
  2368. /*       <add_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2369. static CompileErrors    ParseExpr5(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2370.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2371.                                                 long* LineNumberOut)
  2372.     {
  2373.         CompileErrors                Error;
  2374.         ASTExpressionRec*        LeftHandSide;
  2375.  
  2376.         CheckPtrExistence(Scanner);
  2377.         CheckPtrExistence(SymbolTable);
  2378.         CheckPtrExistence(TrashTracker);
  2379.  
  2380.         Error = ParseExpr6(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2381.         if (Error != eCompileNoError)
  2382.             {
  2383.                 return Error;
  2384.             }
  2385.  
  2386.         return ParseExpr5Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2387.             TrashTracker,LineNumberOut);
  2388.     }
  2389.  
  2390.  
  2391.  
  2392.  
  2393. /*   43:   <expr4prime>       ::= <add_oper> <expr5> <expr4prime> */
  2394. /*   44:                      ::=  */
  2395. /* FIRST SET: */
  2396. /*  <expr4prime>       : {+, -, <add_oper>} */
  2397. /* FOLLOW SET: */
  2398. /*  <expr4prime>       : {and, or, xor, then, else, elseif, while, until, */
  2399. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, EQ, NEQ, LT, LTEQ, GR, GREQ, */
  2400. /*       <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <actualtail>, */
  2401. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2402. static CompileErrors    ParseExpr4Prime(ASTExpressionRec** ExpressionOut,
  2403.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2404.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2405.                                                 long* LineNumberOut)
  2406.     {
  2407.         TokenRec*                        Token;
  2408.         BinaryOpType                OperatorType;
  2409.         CompileErrors                Error;
  2410.         ASTExpressionRec*        RightHandSide;
  2411.         ASTBinaryOpRec*            WholeOperator;
  2412.         ASTExpressionRec*        ThisWholeNode;
  2413.  
  2414.         CheckPtrExistence(LeftHandSide);
  2415.         CheckPtrExistence(Scanner);
  2416.         CheckPtrExistence(SymbolTable);
  2417.         CheckPtrExistence(TrashTracker);
  2418.  
  2419.         Token = GetNextToken(Scanner);
  2420.         if (Token == NIL)
  2421.             {
  2422.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2423.                 return eCompileOutOfMemory;
  2424.             }
  2425.  
  2426.         switch (GetTokenType(Token))
  2427.             {
  2428.                 default:
  2429.                     UngetToken(Scanner,Token);
  2430.                     *ExpressionOut = LeftHandSide;
  2431.                     return eCompileNoError;
  2432.  
  2433.                 case eTokenPlus:
  2434.                 case eTokenMinus:
  2435.                     UngetToken(Scanner,Token);
  2436.                     Error = ParseAddOper(&OperatorType,Scanner,LineNumberOut);
  2437.                     if (Error != eCompileNoError)
  2438.                         {
  2439.                             return Error;
  2440.                         }
  2441.                     Error = ParseExpr5(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2442.                         LineNumberOut);
  2443.                     if (Error != eCompileNoError)
  2444.                         {
  2445.                             return Error;
  2446.                         }
  2447.                     /* create the node */
  2448.                     WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,RightHandSide,
  2449.                         TrashTracker,GetCurrentLineNumber(Scanner));
  2450.                     if (WholeOperator == NIL)
  2451.                         {
  2452.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2453.                             return eCompileOutOfMemory;
  2454.                         }
  2455.                     ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2456.                         GetCurrentLineNumber(Scanner));
  2457.                     if (ThisWholeNode == NIL)
  2458.                         {
  2459.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2460.                             return eCompileOutOfMemory;
  2461.                         }
  2462.                     return ParseExpr4Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2463.                         TrashTracker,LineNumberOut);
  2464.             }
  2465.         EXECUTE(PRERR(ForceAbort,"ParseConjOper:  control reached end of function"));
  2466.     }
  2467.  
  2468.  
  2469.  
  2470.  
  2471. /*   36:   <rel_oper>         ::= LT */
  2472. /*   37:                      ::= LTEQ */
  2473. /*   38:                      ::= GR */
  2474. /*   39:                      ::= GREQ */
  2475. /*   40:                      ::= EQ */
  2476. /*   41:                      ::= NEQ */
  2477. /* FIRST SET: */
  2478. /*  <rel_oper>         : {EQ, NEQ, LT, LTEQ, GR, GREQ} */
  2479. /* FOLLOW SET: */
  2480. /*  <rel_oper>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2481. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2482. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2483. /*       true, false, (, -, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  2484. /*       <expr8>} */
  2485. static CompileErrors    ParseRelOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2486.                                                 long* LineNumberOut)
  2487.     {
  2488.         TokenRec*                        Token;
  2489.  
  2490.         CheckPtrExistence(Scanner);
  2491.  
  2492.         Token = GetNextToken(Scanner);
  2493.         if (Token == NIL)
  2494.             {
  2495.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2496.                 return eCompileOutOfMemory;
  2497.             }
  2498.  
  2499.         switch (GetTokenType(Token))
  2500.             {
  2501.                 default:
  2502.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2503.                     return eCompileExpectedOperatorOrStatement;
  2504.  
  2505.                 case eTokenEqual:
  2506.                     *OperatorOut = eBinaryEqual;
  2507.                     return eCompileNoError;
  2508.  
  2509.                 case eTokenNotEqual:
  2510.                     *OperatorOut = eBinaryNotEqual;
  2511.                     return eCompileNoError;
  2512.  
  2513.                 case eTokenLessThan:
  2514.                     *OperatorOut = eBinaryLessThan;
  2515.                     return eCompileNoError;
  2516.  
  2517.                 case eTokenLessThanOrEqual:
  2518.                     *OperatorOut = eBinaryLessThanOrEqual;
  2519.                     return eCompileNoError;
  2520.  
  2521.                 case eTokenGreaterThan:
  2522.                     *OperatorOut = eBinaryGreaterThan;
  2523.                     return eCompileNoError;
  2524.  
  2525.                 case eTokenGreaterThanOrEqual:
  2526.                     *OperatorOut = eBinaryGreaterThanOrEqual;
  2527.                     return eCompileNoError;
  2528.             }
  2529.         EXECUTE(PRERR(ForceAbort,"ParseRelOper:  control reached end of function"));
  2530.     }
  2531.  
  2532.  
  2533.  
  2534.  
  2535. /*   56:   <expr6>            ::= <unary_oper> <expr6> */
  2536. /*   57:                      ::= <expr7> */
  2537. /* FIRST SET: */
  2538. /*  <expr6>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2539. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2540. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2541. /*       false, (, -, <unary_oper>, <expr7>, <expr8>} */
  2542. /* FOLLOW SET: */
  2543. /*  <expr6>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2544. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, NEQ, */
  2545. /*       LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, */
  2546. /*       <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, <actualtail>, */
  2547. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2548. static CompileErrors    ParseExpr6(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2549.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2550.                                                 long* LineNumberOut)
  2551.     {
  2552.         TokenRec*                        Token;
  2553.         UnaryOpType                    UnaryOperatorThing;
  2554.         ASTExpressionRec*        UnaryArgument;
  2555.         CompileErrors                Error;
  2556.         ASTUnaryOpRec*            UnaryOpNode;
  2557.  
  2558.         CheckPtrExistence(Scanner);
  2559.         CheckPtrExistence(SymbolTable);
  2560.         CheckPtrExistence(TrashTracker);
  2561.  
  2562.         Token = GetNextToken(Scanner);
  2563.         if (Token == NIL)
  2564.             {
  2565.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2566.                 return eCompileOutOfMemory;
  2567.             }
  2568.  
  2569.         switch (GetTokenType(Token))
  2570.             {
  2571.                 default:
  2572.                  OtherPoint:
  2573.                     UngetToken(Scanner,Token);
  2574.                     return ParseExpr7(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2575.  
  2576.                 case eTokenMinus:
  2577.                     UnaryOperatorThing = eUnaryNegation;
  2578.                     break;
  2579.  
  2580.                 case eTokenKeyword:
  2581.                     switch (GetTokenKeywordTag(Token))
  2582.                         {
  2583.                             default:
  2584.                                 goto OtherPoint;
  2585.  
  2586.                             case eKeywordNot:
  2587.                                 UnaryOperatorThing = eUnaryNot;
  2588.                                 break;
  2589.  
  2590.                             case eKeywordSin:
  2591.                                 UnaryOperatorThing = eUnarySine;
  2592.                                 break;
  2593.  
  2594.                             case eKeywordCos:
  2595.                                 UnaryOperatorThing = eUnaryCosine;
  2596.                                 break;
  2597.  
  2598.                             case eKeywordTan:
  2599.                                 UnaryOperatorThing = eUnaryTangent;
  2600.                                 break;
  2601.  
  2602.                             case eKeywordAsin:
  2603.                                 UnaryOperatorThing = eUnaryArcSine;
  2604.                                 break;
  2605.  
  2606.                             case eKeywordAcos:
  2607.                                 UnaryOperatorThing = eUnaryArcCosine;
  2608.                                 break;
  2609.  
  2610.                             case eKeywordAtan:
  2611.                                 UnaryOperatorThing = eUnaryArcTangent;
  2612.                                 break;
  2613.  
  2614.                             case eKeywordLn:
  2615.                                 UnaryOperatorThing = eUnaryLogarithm;
  2616.                                 break;
  2617.  
  2618.                             case eKeywordExp:
  2619.                                 UnaryOperatorThing = eUnaryExponentiation;
  2620.                                 break;
  2621.  
  2622.                             case eKeywordBool:
  2623.                                 UnaryOperatorThing = eUnaryCastToBoolean;
  2624.                                 break;
  2625.  
  2626.                             case eKeywordInt:
  2627.                                 UnaryOperatorThing = eUnaryCastToInteger;
  2628.                                 break;
  2629.  
  2630.                             case eKeywordSingle:
  2631.                                 UnaryOperatorThing = eUnaryCastToSingle;
  2632.                                 break;
  2633.  
  2634.                             case eKeywordDouble:
  2635.                                 UnaryOperatorThing = eUnaryCastToDouble;
  2636.                                 break;
  2637.  
  2638.                             case eKeywordFixed:
  2639.                                 UnaryOperatorThing = eUnaryCastToFixed;
  2640.                                 break;
  2641.  
  2642.                             case eKeywordSqr:
  2643.                                 UnaryOperatorThing = eUnarySquare;
  2644.                                 break;
  2645.  
  2646.                             case eKeywordSqrt:
  2647.                                 UnaryOperatorThing = eUnarySquareRoot;
  2648.                                 break;
  2649.  
  2650.                             case eKeywordAbs:
  2651.                                 UnaryOperatorThing = eUnaryAbsoluteValue;
  2652.                                 break;
  2653.  
  2654.                             case eKeywordNeg:
  2655.                                 UnaryOperatorThing = eUnaryTestNegative;
  2656.                                 break;
  2657.  
  2658.                             case eKeywordSign:
  2659.                                 UnaryOperatorThing = eUnaryGetSign;
  2660.                                 break;
  2661.  
  2662.                             case eKeywordLength:
  2663.                                 UnaryOperatorThing = eUnaryGetArrayLength;
  2664.                                 break;
  2665.                         }
  2666.                     break;
  2667.             }
  2668.  
  2669.         /* build argument */
  2670.         Error = ParseExpr6(&UnaryArgument,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2671.         if (Error != eCompileNoError)
  2672.             {
  2673.                 return Error;
  2674.             }
  2675.  
  2676.         /* build node */
  2677.         UnaryOpNode = NewUnaryOperator(UnaryOperatorThing,UnaryArgument,TrashTracker,
  2678.             GetCurrentLineNumber(Scanner));
  2679.         if (UnaryOpNode == NIL)
  2680.             {
  2681.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2682.                 return eCompileOutOfMemory;
  2683.             }
  2684.  
  2685.         *ExpressionOut = NewExprUnaryOperator(UnaryOpNode,TrashTracker,
  2686.             GetCurrentLineNumber(Scanner));
  2687.         if (*ExpressionOut == NIL)
  2688.             {
  2689.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2690.                 return eCompileOutOfMemory;
  2691.             }
  2692.  
  2693.         return eCompileNoError;
  2694.     }
  2695.  
  2696.  
  2697.  
  2698.  
  2699. /*   48:   <expr5prime>       ::= <mult_oper> <expr6> <expr5prime> */
  2700. /*   49:                      ::=  */
  2701. /* FIRST SET: */
  2702. /*  <expr5prime>       : {div, mod, SHR, SHL, *, /, <mult_oper>} */
  2703. /* FOLLOW SET: */
  2704. /*  <expr5prime>       : {and, or, xor, then, else, elseif, while, until, */
  2705. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, +, -, EQ, NEQ, LT, LTEQ, GR, */
  2706. /*       GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <expr4prime>, */
  2707. /*       <add_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2708. static CompileErrors    ParseExpr5Prime(ASTExpressionRec** ExpressionOut,
  2709.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2710.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2711.                                                 long* LineNumberOut)
  2712.     {
  2713.         TokenRec*                        Token;
  2714.         ASTExpressionRec*        RightHandSide;
  2715.         BinaryOpType                OperatorThing;
  2716.         CompileErrors                Error;
  2717.         ASTBinaryOpRec*            BinaryOperator;
  2718.         ASTExpressionRec*        WholeThingThing;
  2719.  
  2720.         CheckPtrExistence(LeftHandSide);
  2721.         CheckPtrExistence(Scanner);
  2722.         CheckPtrExistence(SymbolTable);
  2723.         CheckPtrExistence(TrashTracker);
  2724.  
  2725.         Token = GetNextToken(Scanner);
  2726.         if (Token == NIL)
  2727.             {
  2728.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2729.                 return eCompileOutOfMemory;
  2730.             }
  2731.  
  2732.         switch (GetTokenType(Token))
  2733.             {
  2734.                 default:
  2735.                  NullifyPoint:
  2736.                     *ExpressionOut = LeftHandSide;
  2737.                     UngetToken(Scanner,Token);
  2738.                     return eCompileNoError;
  2739.  
  2740.                 case eTokenKeyword:
  2741.                     switch (GetTokenKeywordTag(Token))
  2742.                         {
  2743.                             default:
  2744.                                 goto NullifyPoint;
  2745.  
  2746.                             case eKeywordDiv:
  2747.                             case eKeywordMod:
  2748.                              DoTheStuffPoint:
  2749.                                 UngetToken(Scanner,Token);
  2750.                                 Error = ParseMultOper(&OperatorThing,Scanner,LineNumberOut);
  2751.                                 if (Error != eCompileNoError)
  2752.                                     {
  2753.                                         return Error;
  2754.                                     }
  2755.                                 Error = ParseExpr6(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2756.                                     LineNumberOut);
  2757.                                 if (Error != eCompileNoError)
  2758.                                     {
  2759.                                         return Error;
  2760.                                     }
  2761.                                 /* create the node */
  2762.                                 BinaryOperator = NewBinaryOperator(OperatorThing,LeftHandSide,
  2763.                                     RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2764.                                 if (BinaryOperator == NIL)
  2765.                                     {
  2766.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2767.                                         return eCompileOutOfMemory;
  2768.                                     }
  2769.                                 WholeThingThing = NewExprBinaryOperator(BinaryOperator,TrashTracker,
  2770.                                     GetCurrentLineNumber(Scanner));
  2771.                                 if (WholeThingThing == NIL)
  2772.                                     {
  2773.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2774.                                         return eCompileOutOfMemory;
  2775.                                     }
  2776.                                 return ParseExpr5Prime(ExpressionOut,WholeThingThing,Scanner,
  2777.                                     SymbolTable,TrashTracker,LineNumberOut);
  2778.                         }
  2779.                     break;
  2780.  
  2781.                 case eTokenShiftLeft:
  2782.                 case eTokenShiftRight:
  2783.                 case eTokenStar:
  2784.                 case eTokenSlash:
  2785.                     goto DoTheStuffPoint;
  2786.             }
  2787.         EXECUTE(PRERR(ForceAbort,"ParseExpr5Prime:  control reached end of function"));
  2788.     }
  2789.  
  2790.  
  2791.  
  2792.  
  2793. /*   45:   <add_oper>         ::= + */
  2794. /*   46:                      ::= - */
  2795. /*  <add_oper>         : {+, -} */
  2796. /*  <add_oper>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2797. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2798. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2799. /*       true, false, (, -, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2800. static CompileErrors    ParseAddOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2801.                                                 long* LineNumberOut)
  2802.     {
  2803.         TokenRec*                        Token;
  2804.  
  2805.         CheckPtrExistence(Scanner);
  2806.  
  2807.         Token = GetNextToken(Scanner);
  2808.         if (Token == NIL)
  2809.             {
  2810.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2811.                 return eCompileOutOfMemory;
  2812.             }
  2813.  
  2814.         switch (GetTokenType(Token))
  2815.             {
  2816.                 default:
  2817.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2818.                     return eCompileExpectedOperatorOrStatement;
  2819.  
  2820.                 case eTokenPlus:
  2821.                     *OperatorOut = eBinaryPlus;
  2822.                     return eCompileNoError;
  2823.  
  2824.                 case eTokenMinus:
  2825.                     *OperatorOut = eBinaryMinus;
  2826.                     return eCompileNoError;
  2827.             }
  2828.         EXECUTE(PRERR(ForceAbort,"ParseAddOper:  control reached end of function"));
  2829.     }
  2830.  
  2831.  
  2832.  
  2833.  
  2834. /*   79:   <expr7>            ::= <expr8> <expr7prime> */
  2835. /* FIRST SET: */
  2836. /*  <expr7>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2837. /*       <string>, true, false, (, <expr8>} */
  2838. /* FOLLOW SET: */
  2839. /*  <expr7>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2840. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, NEQ, */
  2841. /*       LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, */
  2842. /*       <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, <actualtail>, */
  2843. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2844. static CompileErrors    ParseExpr7(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2845.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2846.                                                 long* LineNumberOut)
  2847.     {
  2848.         ASTExpressionRec*        ResultOfExpr8;
  2849.         CompileErrors                Error;
  2850.  
  2851.         CheckPtrExistence(Scanner);
  2852.         CheckPtrExistence(SymbolTable);
  2853.         CheckPtrExistence(TrashTracker);
  2854.  
  2855.         Error = ParseExpr8(&ResultOfExpr8,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2856.         if (Error != eCompileNoError)
  2857.             {
  2858.                 return Error;
  2859.             }
  2860.  
  2861.         return ParseExpr7Prime(ExpressionOut,ResultOfExpr8,Scanner,SymbolTable,TrashTracker,
  2862.             LineNumberOut);
  2863.     }
  2864.  
  2865.  
  2866.  
  2867.  
  2868. /*   50:   <mult_oper>        ::= * */
  2869. /*   51:                      ::= / */
  2870. /*   52:                      ::= div */
  2871. /*   53:                      ::= mod */
  2872. /*   54:                      ::= SHL */
  2873. /*   55:                      ::= SHR */
  2874. /*  <mult_oper>        : {div, mod, SHR, SHL, *, /} */
  2875. /*  <mult_oper>        : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2876. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2877. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2878. /*       true, false, (, -, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2879. static CompileErrors    ParseMultOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2880.                                                 long* LineNumberOut)
  2881.     {
  2882.         TokenRec*                        Token;
  2883.  
  2884.         CheckPtrExistence(Scanner);
  2885.  
  2886.         Token = GetNextToken(Scanner);
  2887.         if (Token == NIL)
  2888.             {
  2889.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2890.                 return eCompileOutOfMemory;
  2891.             }
  2892.  
  2893.         switch (GetTokenType(Token))
  2894.             {
  2895.                 default:
  2896.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2897.                     return eCompileExpectedOperatorOrStatement;
  2898.  
  2899.                 case eTokenStar:
  2900.                     *OperatorOut = eBinaryMultiplication;
  2901.                     return eCompileNoError;
  2902.  
  2903.                 case eTokenSlash:
  2904.                     *OperatorOut = eBinaryImpreciseDivision;
  2905.                     return eCompileNoError;
  2906.  
  2907.                 case eTokenShiftLeft:
  2908.                     *OperatorOut = eBinaryShiftLeft;
  2909.                     return eCompileNoError;
  2910.  
  2911.                 case eTokenShiftRight:
  2912.                     *OperatorOut = eBinaryShiftRight;
  2913.                     return eCompileNoError;
  2914.  
  2915.                 case eTokenKeyword:
  2916.                     switch (GetTokenKeywordTag(Token))
  2917.                         {
  2918.                             default:
  2919.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2920.                                 return eCompileExpectedOperatorOrStatement;
  2921.  
  2922.                             case eKeywordDiv:
  2923.                                 *OperatorOut = eBinaryIntegerDivision;
  2924.                                 return eCompileNoError;
  2925.  
  2926.                             case eKeywordMod:
  2927.                                 *OperatorOut = eBinaryIntegerRemainder;
  2928.                                 return eCompileNoError;
  2929.                         }
  2930.                     break;
  2931.             }
  2932.         EXECUTE(PRERR(ForceAbort,"ParseMultOper:  control reached end of function"));
  2933.     }
  2934.  
  2935.  
  2936.  
  2937.  
  2938. /*   92:   <expr8>            ::= <identifier> */
  2939. /*   93:                      ::= <integer> */
  2940. /*   94:                      ::= <single> */
  2941. /*   95:                      ::= <double> */
  2942. /*   96:                      ::= <fixed> */
  2943. /*   97:                      ::= <string> */
  2944. /*   98:                      ::= true */
  2945. /*   99:                      ::= false */
  2946. /*  108:                      ::= ( <exprlist> ) */
  2947. /*  <expr8>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2948. /*       <string>, true, false, (} */
  2949. /*  <expr8>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2950. /*       while, until, do, to, (, ), OPENBRACKET, CLOSEBRACKET, ,, :=, ;, *, */
  2951. /*       /, +, -, ^, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  2952. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  2953. /*       <mult_oper>, <expr7prime>, <arraysubscript>, <funccall>, <exponentiation>, */
  2954. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2955. static CompileErrors    ParseExpr8(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2956.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2957.                                                 long* LineNumberOut)
  2958.     {
  2959.         ASTOperandRec*            TheOperand;
  2960.         TokenRec*                        Token;
  2961.  
  2962.         CheckPtrExistence(Scanner);
  2963.         CheckPtrExistence(SymbolTable);
  2964.         CheckPtrExistence(TrashTracker);
  2965.  
  2966.         Token = GetNextToken(Scanner);
  2967.         if (Token == NIL)
  2968.             {
  2969.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2970.                 return eCompileOutOfMemory;
  2971.             }
  2972.  
  2973.         switch (GetTokenType(Token))
  2974.             {
  2975.                 default:
  2976.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2977.                     return eCompileExpectedOperand;
  2978.  
  2979.                     /*   92:   <expr8>            ::= <identifier> */
  2980.                 case eTokenIdentifier:
  2981.                     {
  2982.                         SymbolRec*                TheSymbolTableEntry;
  2983.  
  2984.                         TheSymbolTableEntry = GetSymbolFromTable(SymbolTable,
  2985.                             GetTokenIdentifierString(Token),PtrSize(GetTokenIdentifierString(Token)));
  2986.                         if (TheSymbolTableEntry == NIL)
  2987.                             {
  2988.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2989.                                 return eCompileIdentifierNotDeclared;
  2990.                             }
  2991.                         TheOperand = NewSymbolReference(TrashTracker,TheSymbolTableEntry,
  2992.                             GetCurrentLineNumber(Scanner));
  2993.                     }
  2994.                     break;
  2995.  
  2996.                     /*   93:                      ::= <integer> */
  2997.                 case eTokenInteger:
  2998.                     TheOperand = NewIntegerLiteral(TrashTracker,GetTokenIntegerValue(Token),
  2999.                         GetCurrentLineNumber(Scanner));
  3000.                     break;
  3001.  
  3002.                     /*   94:                      ::= <single> */
  3003.                 case eTokenSingle:
  3004.                     TheOperand = NewSingleLiteral(TrashTracker,GetTokenSingleValue(Token),
  3005.                         GetCurrentLineNumber(Scanner));
  3006.                     break;
  3007.  
  3008.                     /*   95:                      ::= <double> */
  3009.                 case eTokenDouble:
  3010.                     TheOperand = NewDoubleLiteral(TrashTracker,GetTokenDoubleValue(Token),
  3011.                         GetCurrentLineNumber(Scanner));
  3012.                     break;
  3013.  
  3014.                     /*   96:                      ::= <fixed> */
  3015.                 case eTokenFixed:
  3016.                     TheOperand = NewFixedLiteral(TrashTracker,GetTokenFixedValue(Token),
  3017.                         GetCurrentLineNumber(Scanner));
  3018.                     break;
  3019.  
  3020.                     /*   97:                      ::= <string> */
  3021.                 case eTokenString:
  3022.                     /* this was here, but I took it out */
  3023.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  3024.                     return eCompileCantHaveStringLiteralThere;
  3025. #if 0
  3026.                     TheOperand = NewStringLiteral(TrashTracker,GetTokenStringValue(Token),
  3027.                         GetCurrentLineNumber(Scanner));
  3028. #endif
  3029.  
  3030.                     /*  108:                      ::= ( <exprlist> ) */
  3031.                 case eTokenOpenParen:
  3032.                     {
  3033.                         CompileErrors            Error;
  3034.                         ASTExprListRec*        ListOfExpressions;
  3035.  
  3036.                         /* open a new scope */
  3037.                         if (!IncrementSymbolTableLevel(SymbolTable))
  3038.                             {
  3039.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3040.                                 return eCompileOutOfMemory;
  3041.                             }
  3042.  
  3043.                         /* parse the expression sequence */
  3044.                         Error = ParseExprList(&ListOfExpressions,Scanner,SymbolTable,TrashTracker,
  3045.                             LineNumberOut);
  3046.                         if (Error != eCompileNoError)
  3047.                             {
  3048.                                 return Error;
  3049.                             }
  3050.  
  3051.                         /* dispose of the current scope */
  3052.                         DecrementSymbolTableLevel(SymbolTable);
  3053.  
  3054.                         /* build the thing */
  3055.                         *ExpressionOut = NewExprSequence(ListOfExpressions,TrashTracker,
  3056.                             GetCurrentLineNumber(Scanner));
  3057.                         if (*ExpressionOut == NIL)
  3058.                             {
  3059.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3060.                                 return eCompileOutOfMemory;
  3061.                             }
  3062.  
  3063.                         /* clean up by getting rid of the close paren */
  3064.                         Token = GetNextToken(Scanner);
  3065.                         if (Token == NIL)
  3066.                             {
  3067.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3068.                                 return eCompileOutOfMemory;
  3069.                             }
  3070.                         if (GetTokenType(Token) != eTokenCloseParen)
  3071.                             {
  3072.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3073.                                 return eCompileExpectedCloseParen;
  3074.                             }
  3075.                     }
  3076.                     return eCompileNoError;
  3077.  
  3078.                 case eTokenKeyword:
  3079.                     switch (GetTokenKeywordTag(Token))
  3080.                         {
  3081.                             default:
  3082.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3083.                                 return eCompileExpectedOperand;
  3084.  
  3085.                                 /*   98:                      ::= true */
  3086.                             case eKeywordTrue:
  3087.                                 TheOperand = NewBooleanLiteral(TrashTracker,True,
  3088.                                     GetCurrentLineNumber(Scanner));
  3089.                                 break;
  3090.  
  3091.                                 /*   99:                      ::= false */
  3092.                             case eKeywordFalse:
  3093.                                 TheOperand = NewBooleanLiteral(TrashTracker,False,
  3094.                                     GetCurrentLineNumber(Scanner));
  3095.                                 break;
  3096.  
  3097.                                 /* this was added later. */
  3098.                             case eKeywordPi:
  3099.                                 TheOperand = NewDoubleLiteral(TrashTracker,DGETPI(),
  3100.                                     GetCurrentLineNumber(Scanner));
  3101.                                 break;
  3102.                         }
  3103.                     break;
  3104.             }
  3105.  
  3106.         if (TheOperand == NIL)
  3107.             {
  3108.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3109.                 return eCompileOutOfMemory;
  3110.             }
  3111.  
  3112.         *ExpressionOut = NewExprOperand(TheOperand,TrashTracker,
  3113.             GetCurrentLineNumber(Scanner));
  3114.         if (*ExpressionOut == NIL)
  3115.             {
  3116.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3117.                 return eCompileOutOfMemory;
  3118.             }
  3119.  
  3120.         return eCompileNoError;
  3121.     }
  3122.  
  3123.  
  3124.  
  3125.  
  3126. /*   80:   <expr7prime>       ::= <arraysubscript> */
  3127. /*   81:                      ::= <funccall> */
  3128. /*   82:                      ::= <exponentiation> */
  3129. /*   83:                      ::=  */
  3130. /*  <expr7prime>       : {(, OPENBRACKET, ^, <arraysubscript>, <funccall>, */
  3131. /*       <exponentiation>} */
  3132. /*  <expr7prime>       : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3133. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, */
  3134. /*       +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3135. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3136. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3137. static CompileErrors    ParseExpr7Prime(ASTExpressionRec** ExpressionOut,
  3138.                                                 ASTExpressionRec* TheExpr8Thing, ScannerRec* Scanner,
  3139.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3140.                                                 long* LineNumberOut)
  3141.     {
  3142.         TokenRec*                        Token;
  3143.  
  3144.         CheckPtrExistence(TheExpr8Thing);
  3145.         CheckPtrExistence(Scanner);
  3146.         CheckPtrExistence(SymbolTable);
  3147.         CheckPtrExistence(TrashTracker);
  3148.  
  3149.         Token = GetNextToken(Scanner);
  3150.         if (Token == NIL)
  3151.             {
  3152.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3153.                 return eCompileOutOfMemory;
  3154.             }
  3155.  
  3156.         switch (GetTokenType(Token))
  3157.             {
  3158.                 default:
  3159.                     UngetToken(Scanner,Token);
  3160.                     *ExpressionOut = TheExpr8Thing;
  3161.                     return eCompileNoError;
  3162.  
  3163.                     /*   81:                      ::= <funccall> */
  3164.                 case eTokenOpenParen:
  3165.                     UngetToken(Scanner,Token);
  3166.                     return ParseFuncCall(ExpressionOut,TheExpr8Thing,Scanner,SymbolTable,
  3167.                         TrashTracker,LineNumberOut);
  3168.  
  3169.                     /*   80:   <expr7prime>       ::= <arraysubscript> */
  3170.                 case eTokenOpenBracket:
  3171.                     UngetToken(Scanner,Token);
  3172.                     return ParseArraySubscript(ExpressionOut,TheExpr8Thing,Scanner,SymbolTable,
  3173.                         TrashTracker,LineNumberOut);
  3174.  
  3175.                     /*   82:                      ::= <exponentiation> */
  3176.                 case eTokenCircumflex:
  3177.                     {
  3178.                         ASTExpressionRec*            RightHandSide;
  3179.                         ASTBinaryOpRec*                TheOperator;
  3180.                         CompileErrors                    Error;
  3181.  
  3182.                         UngetToken(Scanner,Token);
  3183.                         Error = ParseExponentiation(&RightHandSide,Scanner,SymbolTable,
  3184.                             TrashTracker,LineNumberOut);
  3185.                         if (Error != eCompileNoError)
  3186.                             {
  3187.                                 return Error;
  3188.                             }
  3189.                         TheOperator = NewBinaryOperator(eBinaryExponentiation,TheExpr8Thing,
  3190.                             RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  3191.                         if (TheOperator == NIL)
  3192.                             {
  3193.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3194.                                 return eCompileOutOfMemory;
  3195.                             }
  3196.                         *ExpressionOut = NewExprBinaryOperator(TheOperator,TrashTracker,
  3197.                             GetCurrentLineNumber(Scanner));
  3198.                         if (*ExpressionOut == NIL)
  3199.                             {
  3200.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3201.                                 return eCompileOutOfMemory;
  3202.                             }
  3203.                         return eCompileNoError;
  3204.                     }
  3205.             }
  3206.         EXECUTE(PRERR(ForceAbort,"ParseExpr7Prime:  control reached end of function"));
  3207.     }
  3208.  
  3209.  
  3210.  
  3211.  
  3212. /*   85:   <funccall>         ::= ( <actualstart> ) */
  3213. /* FIRST SET: */
  3214. /*  <funccall>         : {(} */
  3215. /* FOLLOW SET: */
  3216. /*  <funccall>         : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  3217. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, */
  3218. /*       NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, */
  3219. /*       <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, */
  3220. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3221. static CompileErrors    ParseFuncCall(ASTExpressionRec** ExpressionOut,
  3222.                                                 ASTExpressionRec* FunctionGenerator, ScannerRec* Scanner,
  3223.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3224.                                                 long* LineNumberOut)
  3225.     {
  3226.         TokenRec*                        Token;
  3227.         ASTExprListRec*            ListOfParameters;
  3228.         CompileErrors                Error;
  3229.         ASTFuncCallRec*            TheFunctionCall;
  3230.  
  3231.         CheckPtrExistence(Scanner);
  3232.         CheckPtrExistence(SymbolTable);
  3233.         CheckPtrExistence(TrashTracker);
  3234.  
  3235.         /* swallow open parenthesis */
  3236.         Token = GetNextToken(Scanner);
  3237.         if (Token == NIL)
  3238.             {
  3239.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3240.                 return eCompileOutOfMemory;
  3241.             }
  3242.         if (GetTokenType(Token) != eTokenOpenParen)
  3243.             {
  3244.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3245.                 return eCompileExpectedOpenParen;
  3246.             }
  3247.  
  3248.         /* parse the argument list */
  3249.         Error = ParseActualStart(&ListOfParameters,Scanner,SymbolTable,TrashTracker,
  3250.             LineNumberOut);
  3251.         if (Error != eCompileNoError)
  3252.             {
  3253.                 return Error;
  3254.             }
  3255.  
  3256.         /* swallow close parenthesis */
  3257.         Token = GetNextToken(Scanner);
  3258.         if (Token == NIL)
  3259.             {
  3260.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3261.                 return eCompileOutOfMemory;
  3262.             }
  3263.         if (GetTokenType(Token) != eTokenCloseParen)
  3264.             {
  3265.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3266.                 return eCompileExpectedCommaOrCloseParen;
  3267.             }
  3268.  
  3269.         TheFunctionCall = NewFunctionCall(ListOfParameters,FunctionGenerator,
  3270.             TrashTracker,GetCurrentLineNumber(Scanner));
  3271.         if (TheFunctionCall == NIL)
  3272.             {
  3273.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3274.                 return eCompileOutOfMemory;
  3275.             }
  3276.  
  3277.         *ExpressionOut = NewExprFunctionCall(TheFunctionCall,TrashTracker,
  3278.             GetCurrentLineNumber(Scanner));
  3279.         if (*ExpressionOut == NIL)
  3280.             {
  3281.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3282.                 return eCompileOutOfMemory;
  3283.             }
  3284.  
  3285.         return eCompileNoError;
  3286.     }
  3287.  
  3288.  
  3289.  
  3290.  
  3291. /*   84:   <arraysubscript>   ::= OPENBRACKET <exprlist> CLOSEBRACKET */
  3292. /* FIRST SET: */
  3293. /*  <arraysubscript>   : {OPENBRACKET} */
  3294. /* FOLLOW SET: */
  3295. /*  <arraysubscript>   : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3296. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, */
  3297. /*       /, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3298. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3299. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3300. static CompileErrors    ParseArraySubscript(ASTExpressionRec** ExpressionOut,
  3301.                                                 ASTExpressionRec* ArrayGenerator, ScannerRec* Scanner,
  3302.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3303.                                                 long* LineNumberOut)
  3304.     {
  3305.         TokenRec*                        Token;
  3306.         ASTExpressionRec*        Subscript;
  3307.         CompileErrors                Error;
  3308.         ASTBinaryOpRec*            ArraySubsOperation;
  3309.         ASTExprListRec*            SubscriptRaw;
  3310.  
  3311.         CheckPtrExistence(ArrayGenerator);
  3312.         CheckPtrExistence(Scanner);
  3313.         CheckPtrExistence(SymbolTable);
  3314.         CheckPtrExistence(TrashTracker);
  3315.  
  3316.         Token = GetNextToken(Scanner);
  3317.         if (Token == NIL)
  3318.             {
  3319.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3320.                 return eCompileOutOfMemory;
  3321.             }
  3322.         if (GetTokenType(Token) != eTokenOpenBracket)
  3323.             {
  3324.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3325.                 return eCompileExpectedOpenBracket;
  3326.             }
  3327.  
  3328.         Error = ParseExprList(&SubscriptRaw,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3329.         if (Error != eCompileNoError)
  3330.             {
  3331.                 return Error;
  3332.             }
  3333.         Subscript = NewExprSequence(SubscriptRaw,TrashTracker,GetCurrentLineNumber(Scanner));
  3334.         if (Subscript == NIL)
  3335.             {
  3336.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3337.                 return eCompileOutOfMemory;
  3338.             }
  3339.  
  3340.         Token = GetNextToken(Scanner);
  3341.         if (Token == NIL)
  3342.             {
  3343.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3344.                 return eCompileOutOfMemory;
  3345.             }
  3346.         if (GetTokenType(Token) != eTokenCloseBracket)
  3347.             {
  3348.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3349.                 return eCompileExpectedCloseBracket;
  3350.             }
  3351.  
  3352.         ArraySubsOperation = NewBinaryOperator(eBinaryArraySubscripting,ArrayGenerator,
  3353.             Subscript,TrashTracker,GetCurrentLineNumber(Scanner));
  3354.         if (ArraySubsOperation == NIL)
  3355.             {
  3356.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3357.                 return eCompileOutOfMemory;
  3358.             }
  3359.         *ExpressionOut = NewExprBinaryOperator(ArraySubsOperation,TrashTracker,
  3360.             GetCurrentLineNumber(Scanner));
  3361.         if (*ExpressionOut == NIL)
  3362.             {
  3363.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3364.                 return eCompileOutOfMemory;
  3365.             }
  3366.  
  3367.         return eCompileNoError;
  3368.     }
  3369.  
  3370.  
  3371.  
  3372.  
  3373. /*  124:   <exprlist>         ::= <exprlistelem> <exprlisttail> */
  3374. /* FIRST SET: */
  3375. /*  <exprlist>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  3376. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, */
  3377. /*       cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, */
  3378. /*       length, if, while, until, do, resize, error, true, false, */
  3379. /*       set, (, -, <prototype>, <expr>, <expr2>, <expr3>, <expr4>, <expr5>, */
  3380. /*       <expr6>, <unary_oper>, <expr7>, <expr8>, <whileloop>, <untilloop>} */
  3381. /* FOLLOW SET: */
  3382. /*  <exprlist>         : {), CLOSEBRACKET, EOF} */
  3383. CompileErrors                    ParseExprList(ASTExprListRec** ExpressionOut,
  3384.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3385.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3386.     {
  3387.         CompileErrors                Error;
  3388.         ASTExpressionRec*        FirstExpression;
  3389.         TokenRec*                        Token;
  3390.         ASTExprListRec*            RestOfList;
  3391.  
  3392.         CheckPtrExistence(Scanner);
  3393.         CheckPtrExistence(SymbolTable);
  3394.         CheckPtrExistence(TrashTracker);
  3395.  
  3396.         Token = GetNextToken(Scanner);
  3397.         if (Token == NIL)
  3398.             {
  3399.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3400.                 return eCompileOutOfMemory;
  3401.             }
  3402.  
  3403.         if ((GetTokenType(Token) == eTokenCloseParen)
  3404.             || (GetTokenType(Token) == eTokenCloseBracket)
  3405.             || (GetTokenType(Token) == eTokenEndOfInput))
  3406.             {
  3407.                 UngetToken(Scanner,Token);
  3408.                 *ExpressionOut = NIL; /* empty list */
  3409.                 return eCompileNoError;
  3410.             }
  3411.  
  3412.         /* see if we should parse a non-existent element (prototype) which */
  3413.         /* generates no code */
  3414.         if ((GetTokenType(Token) == eTokenKeyword)
  3415.             && (GetTokenKeywordTag(Token) == eKeywordProto))
  3416.             {
  3417.                 SymbolRec*                    ProtoSymbolOut;
  3418.                 CompileErrors                Error;
  3419.  
  3420.                 UngetToken(Scanner,Token);
  3421.                 Error = ParsePrototype(&ProtoSymbolOut,Scanner,SymbolTable,
  3422.                     TrashTracker,LineNumberOut);
  3423.                 if (Error != eCompileNoError)
  3424.                     {
  3425.                         return Error;
  3426.                     }
  3427.                 /* this is declarative and generates no code */
  3428.                 /* as a hack to get this to work, we'll expect a semicolon and */
  3429.                 /* another expression list */
  3430.                 Token = GetNextToken(Scanner);
  3431.                 if (Token == NIL)
  3432.                     {
  3433.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3434.                         return eCompileOutOfMemory;
  3435.                     }
  3436.                 /* eat up the semicolon */
  3437.                 if (GetTokenType(Token) != eTokenSemicolon)
  3438.                     {
  3439.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3440.                         return eCompilePrototypeCantBeLastThingInExprList;
  3441.                     }
  3442.                 /* now just parse the rest of the expression list */
  3443.                 return ParseExprList(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  3444.                     LineNumberOut);
  3445.             }
  3446.  
  3447.         /* get first part of list */
  3448.         UngetToken(Scanner,Token);
  3449.         Error = ParseExprListElem(&FirstExpression,Scanner,SymbolTable,TrashTracker,
  3450.             LineNumberOut);
  3451.         if (Error != eCompileNoError)
  3452.             {
  3453.                 return Error;
  3454.             }
  3455.  
  3456.         /* get the rest of the list */
  3457.         Error = ParseExprListTail(&RestOfList,Scanner,SymbolTable,TrashTracker,
  3458.             LineNumberOut);
  3459.         if (Error != eCompileNoError)
  3460.             {
  3461.                 return Error;
  3462.             }
  3463.  
  3464.         *ExpressionOut = ASTExprListCons(FirstExpression,RestOfList,TrashTracker);
  3465.         if (*ExpressionOut == NIL)
  3466.             {
  3467.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3468.                 return eCompileOutOfMemory;
  3469.             }
  3470.  
  3471.         return eCompileNoError;
  3472.     }
  3473.  
  3474.  
  3475.  
  3476.  
  3477. /*   91:   <exponentiation>   ::= ^ <expr7> */
  3478. /* FIRST SET: */
  3479. /*  <exponentiation>   : {^} */
  3480. /* FOLLOW SET: */
  3481. /*  <exponentiation>   : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3482. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, */
  3483. /*       /, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3484. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3485. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3486. static CompileErrors    ParseExponentiation(ASTExpressionRec** ExpressionOut,
  3487.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3488.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3489.     {
  3490.         TokenRec*                        Token;
  3491.  
  3492.         CheckPtrExistence(Scanner);
  3493.         CheckPtrExistence(SymbolTable);
  3494.         CheckPtrExistence(TrashTracker);
  3495.  
  3496.         Token = GetNextToken(Scanner);
  3497.         if (Token == NIL)
  3498.             {
  3499.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3500.                 return eCompileOutOfMemory;
  3501.             }
  3502.         if (GetTokenType(Token) != eTokenCircumflex)
  3503.             {
  3504.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3505.                 return eCompileExpectedRightAssociativeOperator;
  3506.             }
  3507.  
  3508.         return ParseExpr7(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3509.     }
  3510.  
  3511.  
  3512.  
  3513.  
  3514. /*   86:   <actualstart>      ::= <actuallist> */
  3515. /*   87:                      ::=  */
  3516. /* FIRST SET: */
  3517. /*  <actualstart>      : {<identifier>, <integer>, <single>, <double>, */
  3518. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, var, */
  3519. /*       not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, */
  3520. /*       neg, sign, length, if, while, until, do, resize, error, */
  3521. /*       true, false, set, (, -, <prototype>, <expr>, <expr2>, */
  3522. /*       <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>, */
  3523. /*       <actuallist>, <whileloop>, <untilloop>} */
  3524. /* FOLLOW SET: */
  3525. /*  <actualstart>      : {)} */
  3526. static CompileErrors    ParseActualStart(ASTExprListRec** ParamListOut,
  3527.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3528.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3529.     {
  3530.         TokenRec*                        Token;
  3531.  
  3532.         CheckPtrExistence(Scanner);
  3533.         CheckPtrExistence(SymbolTable);
  3534.         CheckPtrExistence(TrashTracker);
  3535.  
  3536.         Token = GetNextToken(Scanner);
  3537.         if (Token == NIL)
  3538.             {
  3539.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3540.                 return eCompileOutOfMemory;
  3541.             }
  3542.  
  3543.         /* handle the nullification */
  3544.         if (GetTokenType(Token) == eTokenCloseParen)
  3545.             {
  3546.                 UngetToken(Scanner,Token);
  3547.                 *ParamListOut = NIL; /* empty list is NIL */
  3548.                 return eCompileNoError;
  3549.             }
  3550.  
  3551.         UngetToken(Scanner,Token);
  3552.         return ParseActualList(ParamListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3553.     }
  3554.  
  3555.  
  3556.  
  3557.  
  3558. /*   88:   <actuallist>       ::= <expr> <actualtail> */
  3559. /* FIRST SET: */
  3560. /*  <actuallist>       : {<identifier>, <integer>, <single>, <double>, */
  3561. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, var, */
  3562. /*       not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, */
  3563. /*       neg, sign, length, if, while, until, do, resize, error, */
  3564. /*       true, false, set, (, -, <prototype>, <expr>, <expr2>, */
  3565. /*       <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>, */
  3566. /*       <whileloop>, <untilloop>} */
  3567. /* FOLLOW SET: */
  3568. /*  <actuallist>       : {)} */
  3569. static CompileErrors    ParseActualList(ASTExprListRec** ParamListOut,
  3570.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3571.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3572.     {
  3573.         ASTExpressionRec*        FirstExpression;
  3574.         CompileErrors                Error;
  3575.         ASTExprListRec*            RestOfList;
  3576.  
  3577.         CheckPtrExistence(Scanner);
  3578.         CheckPtrExistence(SymbolTable);
  3579.         CheckPtrExistence(TrashTracker);
  3580.  
  3581.         Error = ParseExpr(&FirstExpression,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3582.         if (Error != eCompileNoError)
  3583.             {
  3584.                 return Error;
  3585.             }
  3586.  
  3587.         Error = ParseActualTail(&RestOfList,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3588.         if (Error != eCompileNoError)
  3589.             {
  3590.                 return Error;
  3591.             }
  3592.  
  3593.         *ParamListOut = ASTExprListCons(FirstExpression,RestOfList,TrashTracker);
  3594.         if (*ParamListOut == NIL)
  3595.             {
  3596.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3597.                 return eCompileOutOfMemory;
  3598.             }
  3599.  
  3600.         return eCompileNoError;
  3601.     }
  3602.  
  3603.  
  3604.  
  3605.  
  3606. /*   89:   <actualtail>       ::= , <actuallist> */
  3607. /*   90:                      ::=  */
  3608. /* FIRST SET: */
  3609. /*  <actualtail>       : {,} */
  3610. /* FOLLOW SET: */
  3611. /*  <actualtail>       : {)} */
  3612. static CompileErrors    ParseActualTail(ASTExprListRec** ParamListOut,
  3613.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3614.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3615.     {
  3616.         TokenRec*                        Token;
  3617.  
  3618.         CheckPtrExistence(Scanner);
  3619.         CheckPtrExistence(SymbolTable);
  3620.         CheckPtrExistence(TrashTracker);
  3621.  
  3622.         Token = GetNextToken(Scanner);
  3623.         if (Token == NIL)
  3624.             {
  3625.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3626.                 return eCompileOutOfMemory;
  3627.             }
  3628.         if ((GetTokenType(Token) != eTokenComma)
  3629.             && (GetTokenType(Token) != eTokenCloseParen))
  3630.             {
  3631.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3632.                 return eCompileExpectedCommaOrCloseParen;
  3633.             }
  3634.  
  3635.         /* handle nullification */
  3636.         if (GetTokenType(Token) == eTokenCloseParen)
  3637.             {
  3638.                 UngetToken(Scanner,Token);
  3639.                 *ParamListOut = NIL; /* empty list */
  3640.                 return eCompileNoError;
  3641.             }
  3642.  
  3643.         return ParseActualList(ParamListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3644.     }
  3645.  
  3646.  
  3647.  
  3648.  
  3649. /*  125:   <exprlisttail>     ::= ; <exprlist> */
  3650. /*  126:                      ::=  */
  3651. /* FIRST SET: */
  3652. /*  <exprlisttail>     : {;} */
  3653. /* FOLLOW SET: */
  3654. /*  <exprlisttail>     : {), CLOSEBRACKET, EOF} */
  3655. static CompileErrors    ParseExprListTail(ASTExprListRec** ListOut,
  3656.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3657.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3658.     {
  3659.         TokenRec*                        Token;
  3660.  
  3661.         CheckPtrExistence(Scanner);
  3662.         CheckPtrExistence(SymbolTable);
  3663.         CheckPtrExistence(TrashTracker);
  3664.  
  3665.         Token = GetNextToken(Scanner);
  3666.         if (Token == NIL)
  3667.             {
  3668.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3669.                 return eCompileOutOfMemory;
  3670.             }
  3671.  
  3672.         /* find out if we should continue or not */
  3673.         if ((GetTokenType(Token) == eTokenCloseParen)
  3674.             || (GetTokenType(Token) == eTokenCloseBracket)
  3675.             || (GetTokenType(Token) == eTokenEndOfInput))
  3676.             {
  3677.                 UngetToken(Scanner,Token);
  3678.                 *ListOut = NIL; /* empty list */
  3679.                 return eCompileNoError;
  3680.             }
  3681.  
  3682.         if (GetTokenType(Token) != eTokenSemicolon)
  3683.             {
  3684.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3685.                 return eCompileExpectedSemicolon;
  3686.             }
  3687.  
  3688.         return ParseExprList(ListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3689.     }
  3690.  
  3691.  
  3692.  
  3693.  
  3694. /*  124:   <exprlistelem>     ::= <expr> */
  3695. /*  125:                      ::= var <identifier> : <type> <vartail> */
  3696. /*   22:   <exprlistelem>     ::= <prototype> */
  3697. /* FIRST SET: */
  3698. /*  <exprlistelem>     : {<identifier>, <integer>, <single>, <double>, */
  3699. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, */
  3700. /*       var, not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, */
  3701. /*       abs, neg, sign, length, if, while, until, do, resize, error, */
  3702. /*       true, false, set, (, -, <prototype>, <expr>, */
  3703. /*       <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  3704. /*       <expr8>, <whileloop>, <untilloop>} */
  3705. /* FOLLOW SET: */
  3706. /*  <exprlistelem>     : {), CLOSEBRACKET, ;, <exprlisttail>} */
  3707. static CompileErrors    ParseExprListElem(ASTExpressionRec** ExpressionOut,
  3708.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3709.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3710.     {
  3711.         TokenRec*                        Token;
  3712.  
  3713.         CheckPtrExistence(Scanner);
  3714.         CheckPtrExistence(SymbolTable);
  3715.         CheckPtrExistence(TrashTracker);
  3716.  
  3717.         /* lookahead to see what to do */
  3718.         Token = GetNextToken(Scanner);
  3719.         if (Token == NIL)
  3720.             {
  3721.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3722.                 return eCompileOutOfMemory;
  3723.             }
  3724.  
  3725.         if ((GetTokenType(Token) == eTokenKeyword)
  3726.             && (GetTokenKeywordTag(Token) == eKeywordVar))
  3727.             {
  3728.                 TokenRec*                        VariableName;
  3729.                 DataTypes                        ReturnType;
  3730.                 CompileErrors                Error;
  3731.                 long                                LineNumberForFirstToken;
  3732.  
  3733.                 /* get the identifier */
  3734.                 VariableName = GetNextToken(Scanner);
  3735.                 if (VariableName == NIL)
  3736.                     {
  3737.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3738.                         return eCompileOutOfMemory;
  3739.                     }
  3740.                 if (GetTokenType(VariableName) != eTokenIdentifier)
  3741.                     {
  3742.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3743.                         return eCompileExpectedIdentifier;
  3744.                     }
  3745.                 LineNumberForFirstToken = GetCurrentLineNumber(Scanner);
  3746.  
  3747.                 /* get the colon */
  3748.                 Token = GetNextToken(Scanner);
  3749.                 if (Token == NIL)
  3750.                     {
  3751.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3752.                         return eCompileOutOfMemory;
  3753.                     }
  3754.                 if (GetTokenType(Token) != eTokenColon)
  3755.                     {
  3756.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3757.                         return eCompileExpectedColon;
  3758.                     }
  3759.  
  3760.                 /* get the variable's type */
  3761.                 Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  3762.                 if (Error != eCompileNoError)
  3763.                     {
  3764.                         return Error;
  3765.                     }
  3766.  
  3767.                 /* finish up the declaration of the variable */
  3768.                 return ParseVarTail(ExpressionOut,VariableName,LineNumberForFirstToken,
  3769.                     ReturnType,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3770.             }
  3771.         else
  3772.             {
  3773.                 /* do the other thing */
  3774.                 UngetToken(Scanner,Token);
  3775.                 return ParseExpr(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3776.             }
  3777.     }
  3778.